如何使静态日历线程安全

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

虽然这很糟糕。您可以只使用一个同步方法,每次需要时创建原始日历的克隆,当然......通过调用computeFieldscomputeTime,您可以使后续的读取操作成为线程安全的,当然,但是我不愿意去试试。

另一答案

如果您不更改日历,则日历是线程安全的。您的示例中的用法很好。

值得注意的是,Calendar不是一个高效的类,你应该只将它用于复杂的操作(比如查找下个月/年)恕我直言:如果你确实将它用于复杂的操作,请仅使用局部变量。

如果你只想要它的时间快照,更快的方法是使用currentTimeMillis甚至创建一个对象。如果要使线程安全,可以使字段变为volatile。

private static long now = System.currentTimeMillis();

用法有点怀疑。为什么你会得到当前时间并将其存储在全球范围内。它让我想起了这个老笑话。

- 你有时间吗? - 是的,我把它写在某个地方。

另一答案

你不能。是的,你可以同步它,但它仍然有可变的状态字段。您必须创建自己的Calendar对象。

如果可能的话,使用轻量级的东西,比如长时间以毫秒为单位测量时间,并且只在需要时转换为日历。

另一答案

在方法中创建一个Calendar作为局部变量。如果您需要跨方法的相同日历,您可能正在使用静态,其中(单例或准单例)对象更合适。

以上是关于如何使静态日历线程安全的主要内容,如果未能解决你的问题,请参考以下文章

使用来自其他类的公共静态 HashTable 的同步方法。我怎样才能使这个方法线程安全?

如何安全发布对象

如何使 Stack.Pop 线程安全

创建型设计模式--单例模式

如何轻松使 std::cout 线程安全?

如何使用 AppDomain 限制静态类的范围以进行线程安全使用?