java 如何使静态日历线程安全

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6245053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:59:34  来源:igfitidea点击:

How to make a static Calendar thread safe

javastaticcalendarthread-safety

提问by cody

I'd like to use a Calendar for some static methods and use a static field:

我想将日历用于一些静态方法并使用静态字段:

private static Calendar calendar = Calendar.getInstance();

Now I read java.util.Calendar isn't thread safe. How can I make this thread safe (it should be static)?

现在我读到 java.util.Calendar 不是线程安全的。我怎样才能使这个线程安全(它应该是静态的)?

回答by Jon Skeet

You can't make something thread-safe if it isn't. In the case of Calendar, even readingdata from it isn't thread-safe, as it can update internal data structures.

如果不是,你就不能制作线程安全的东西。在 的情况下Calendar,即使从中读取数据也不是线程安全的,因为它可以更新内部数据结构。

If at all possible, I'd suggest using Joda Timeinstead:

如果可能的话,我建议改用Joda Time

  • Most of the types are immutable
  • The immutable types are thread-safe
  • It's a generally much better API anyway
  • 大多数类型是不可变的
  • 不可变类型是线程安全的
  • 无论如何,它通常是一个更好的API

If you absolutely haveto use a Calendar, you could create a locking object and put all the access through a lock. For example:

如果您绝对必须使用 a 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

It's pretty nasty though. You could have just onesynchronized method which created a clone of the original calendar each time it was needed, of course... it's possible that by calling computeFieldsor computeTimeyou could make subsequentread-operations thread-safe, of course, but personally I'd be loathe to try it.

不过还是挺恶心的。您可以只使用一个同步方法,在每次需要时创建原始日历的克隆,当然……当然,通过调用computeFieldscomputeTime您可以使后续的读取操作线程安全,但就我个人而言,这是可能的不愿意尝试。

回答by Peter Lawrey

Calendar is thread safe provided you don't change it. The usage in your example is fine.

只要您不更改日历,它就是线程安全的。您示例中的用法很好。

It is worth noting that Calendar is not an efficient class and you should only use it for complex operations (like finding the next month/year) IMHO: If you do use it for complex operations, use local variables only.

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

If all you want it a snapshot of the time a faster way is to use currentTimeMillis which does even create an object. You can make the field volatile if you want to make it thread safe.

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

private static long now = System.currentTimeMillis();

The usage is a bit suspect. Why would you get the current time and store it globally like this. It reminds me of the old joke.

用法有点可疑。为什么要获取当前时间并像这样将其全局存储。这让我想起了那个古老的笑话。

- Do you have the time?
- Yes, I have it written down somewhere.

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

回答by MJB

You cannot. Yes, you could synchronize on it, but it still has mutable state fields. You'll have to create your own Calendar object.

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

If possible, use something lightweight, like a long measuring the times in milliseconds, and only convert to a Calendar when you NEED to.

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

回答by Andrew Lazarus

Create a Calendaras a local variable in the method. If you need the same calendar across methods, you may be using statics where a (singleton or quasi-singleton) object would be more appropriate.

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