据我所知java.util.Date
是可变的,所以如果多个线程试图访问和修改它,它就不是线程安全的。我们如何使用客户端锁定或组合(包装器)使其线程安全?
答案 0 :(得分:30)
按此顺序,从最佳到最差:
根本不使用它,请查看jodatime
根本不使用它,使用AtomicLong
或不可变原语long
与volatile
来表示纪元时间
封装它。始终返回Date
的防御性副本,而不是对内部对象的引用
在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
块同步其对象的所有用法。