我想将Calendar用于一些静态方法并使用静态字段:
private static Calendar calendar = Calendar.getInstance();
现在我读java.util.Calendar不是线程安全的。如何使这个线程安全(它应该是静态)?
答案 0 :(得分:14)
如果不是,你不能做一些线程安全的东西。在Calendar
的情况下,即使从中读取数据也不是线程安全的,因为它可以更新内部数据结构。
如果可能的话,我建议改为使用Joda Time:
如果您绝对 使用Calendar
,您可以创建一个锁定对象并通过锁定放置所有访问权限。例如:
private static final Calendar calendar = Calendar.getInstance();
private static final Object calendarLock = new Object();
public static int getYear()
{
synchronized(calendarLock)
{
return calendar.get(Calendar.YEAR);
}
}
// Ditto for other methods
但这很糟糕。您可以只使用一个同步方法,每次需要时创建原始日历的克隆,当然......可以通过调用computeFields
或computeTime
来实现当然,可以使后续读取操作成为线程安全的,但我个人不愿意尝试它。
答案 1 :(得分:4)
如果您不更改日历,则日历是线程安全的。您的示例中的用法很好。
值得注意的是,Calendar不是一个高效的类,你应该只将它用于复杂的操作(比如查找下个月/年)恕我直言:如果你确实将它用于复杂的操作,那么只使用局部变量。
如果你只想要它的时间快照,更快的方法是使用currentTimeMillis甚至创建一个对象。如果要使线程安全,可以使字段变为volatile。
private static long now = System.currentTimeMillis();
用法有点怀疑。为什么你会得到当前时间并将其存储在全球范围内。它让我想起了这个老笑话。
- 你有时间吗?
- 是的,我把它写在某个地方。
答案 2 :(得分:2)
你做不到。是的,你可以同步它,但它仍然有可变的状态字段。您必须创建自己的日历对象。
如果可能,请使用轻量级的内容,例如长时间测量时间(以毫秒为单位),并在需要时仅转换为日历。
答案 3 :(得分:-1)
在方法中创建Calendar
作为局部变量。如果你需要跨方法的相同日历,你可能正在使用静态,其中(单例或准单例)对象更合适。