在Wrapper类线程安全中使用Java 8时间类?

时间:2016-12-13 20:52:10

标签: java multithreading time java-8

我将我们的应用程序使用JodaTime / Java.utils时间转换为Java 8 ...我们经常使用Date(这不是线程安全的),所以而不是更改所有这些引用,我尝试使用Java 8的类并利用它。这就是我想出的:

测试时,它工作正常。我们正在使用Spring,并且有两个ScheduledExecutorTasks(基本上是线程)运行delta作业,并使用"格式"此代码的一部分用于格式化ISO_ZULU格式的日期。

然而,这不起作用。格式化的时间显示不正确,可能导致404错误。很难测试,因为我们的QA服务器运行它,它不会在本地发生。

我的问题是,我在做什么安全?如果没有,是不是因为我使用了Date?使用线程安全类(如Instant)会解决我的问题吗?

{{1}}

1 个答案:

答案 0 :(得分:0)

TL;博士

是。你在做什么似乎是线程安全的。

详细

您在每次通话时传递对java.util.Date对象的引用。该引用未被保留,它在静态方法调用结束时消失。所以没有其他线程看到那个特定的引用,正如dcsohl所评论的那样。

线程安全是关于共享资源的争用。在此处显示的代码中,您未共享Date引用。您可能正在其他可能有问题的线程上的其他代码中共享它。但鉴于你在这里向我们展示了什么,没有问题。

java.time类使用immutable objects并且完全是线程安全的。所以不要担心这方面的事情。

我不知道LogFactory.getLog的线程安全性,但这超出了您的问题的范围。

如果在其他线程中的其他代码中使用了传递Date的{​​{1}},则可能存在其他地方的 。请阅读以下建议,以便不通过Date

建议

其他一些问题,超出了有关线程安全的问题。

调整旧代码,而不是新代码

我建议您将论点从Date更改为Instant。在所有调用代码中,更改调用以传递myExampleDate.toInstant()而不是传递myExampleDate。这使您的代码更加自我记录,因为您正在从遗留日期时间类(Date,{{1}迁移朝向 java.time和远离 },Calendar等)。如果这是目标,那么您不希望将新代码弯曲到旧方法,旧代码应该向新代码弯曲(这样做是低风险/低成本)。

将java.time如何将新转换方法添加到遗留类中,与此处所见的SimpleDateFormat一样灵感。 新类对旧的遗留类一无所知。遗留类有责任使用该程序"。

默认时区

  

private static final String DEFAULT_ZONE_ID = ZoneId.systemDefault()。getId();

这条线不像你想要的那样是最终和永久的。在代码执行时,JVM的当前默认时区可能会在运行时中随时更改。 JVM中任何应用程序的任何线程中的任何代码都可以随时通过调用TimeZone.setDefault来更改当前的默认时区。

此外,Java中必须实现的JVM的默认设置是使用主机操作系统的默认时区的当前值。这是一种超出您控制范围的外部性,因此任何系统管理员都可能无意中改变您应用的行为。同时将时区设置作为参数传递给JVM的启动脚本。

我建议你放弃这一行。相反,始终在所有代码中传递所需/预期的时区。永远不要隐式依赖JVM的当前默认时区。

当你真正想要当前的默认值时,每次都要调用Date.toInstant(),以获得新鲜的事实而不是可能过时的缓存值(不再是真的)。这也使您的代码更加自我记录。

UTC常量

  

private static final String UTC_ZONE_ID =" Etc / UTC";

java.time类已经为UTC提供了一个常量:ZoneOffset.UTC。所以不需要那个常数。