如何使Java.util.Date线程安全

时间:2012-09-03 19:13:30

标签: java multithreading concurrency

据我所知java.util.Date是可变的,所以如果多个线程试图访问和修改它,它就不是线程安全的。我们如何使用客户端锁定或组合(包装器)使其线程安全?

4 个答案:

答案 0 :(得分:30)

按此顺序,从最佳到最差:

  1. 根本不使用它,请查看

  2. 根本不使用它,使用AtomicLong或不可变原语longvolatile来表示纪元时间

  3. 封装它。始终返回Date的防御性副本,而不是对内部对象的引用

  4. Date实例上进行同步。

答案 1 :(得分:4)

您可以使用long值(自Epoch以来的毫秒数)而不是Date实例。分配它将是一个原子操作,它将永远是连贯的。

但是你的问题可能不在于Date值本身,而是在整个算法上,这意味着真正的答案将基于你的真实问题。

以下是多线程上下文中的错误操作示例:

long time;
void add(long duration) {
   time += duration; 
}

这里的问题是你可能有两个并行添加,只有一个有效的添加,因为time += duration不是原子的(它真的是time=time+duration)。

使用long而不是可变对象是不够的。在这种情况下,您可以通过将函数设置为synchronized来解决问题,但其他情况可能更棘手。

答案 2 :(得分:2)

最简单的解决方案是永远不要修改日期,永远不要共享它。即只对局部变量使用Date。

您可以使用JodaTime,因为它具有不可变日期对象。

答案 3 :(得分:-1)

没有简单的解决方案来创建Date类的线程安全包装器。最好的方法是使用synchronized块同步其对象的所有用法。