如何使静态日历线程安全
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使静态日历线程安全相关的知识,希望对你有一定的参考价值。
我想对一些静态方法使用Calendar并使用静态字段:
private static Calendar calendar = Calendar.getInstance();
现在我读java.util.Calendar不是线程安全的。如何使这个线程安全(它应该是静态的)?
如果不是,你不能做一些线程安全的东西。在Calendar
的情况下,即使从中读取数据也不是线程安全的,因为它可以更新内部数据结构。
如果可能的话,我建议使用Joda Time代替:
- 大多数类型是不可变的
- 不可变类型是线程安全的
- 无论如何,它通常是更好的API
如果你绝对必须使用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
,您可以使后续的读取操作成为线程安全的,当然,但是我不愿意去试试。
如果您不更改日历,则日历是线程安全的。您的示例中的用法很好。
值得注意的是,Calendar不是一个高效的类,你应该只将它用于复杂的操作(比如查找下个月/年)恕我直言:如果你确实将它用于复杂的操作,请仅使用局部变量。
如果你只想要它的时间快照,更快的方法是使用currentTimeMillis甚至创建一个对象。如果要使线程安全,可以使字段变为volatile。
private static long now = System.currentTimeMillis();
用法有点怀疑。为什么你会得到当前时间并将其存储在全球范围内。它让我想起了这个老笑话。
- 你有时间吗? - 是的,我把它写在某个地方。
你不能。是的,你可以同步它,但它仍然有可变的状态字段。您必须创建自己的Calendar对象。
如果可能的话,使用轻量级的东西,比如长时间以毫秒为单位测量时间,并且只在需要时转换为日历。
在方法中创建一个Calendar
作为局部变量。如果您需要跨方法的相同日历,您可能正在使用静态,其中(单例或准单例)对象更合适。
以上是关于如何使静态日历线程安全的主要内容,如果未能解决你的问题,请参考以下文章