Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在长寿命的服务器应用程序中高效缓存和更新当前日期_Java_Performance - Fatal编程技术网

Java 在长寿命的服务器应用程序中高效缓存和更新当前日期

Java 在长寿命的服务器应用程序中高效缓存和更新当前日期,java,performance,Java,Performance,我有一个长寿命的服务器应用程序,该应用程序设计为在停机时间最少的情况下运行,例如,24/7操作仅为维护而停止。应用程序必须能够每秒处理数千个请求,因此性能是一个问题 为每个请求提供服务。应用程序的一部分需要知道当前日期是什么,尽管不是时间,但由于第三方API的原因,它必须存储在java.util.date对象中 然而,Date对象的构造成本很高,因此为每个请求创建一个新对象听起来并不明智 在请求之间共享日期对象并每天更新一次意味着在启动时每个服务器工作线程只需要创建一个对象,但如何以安全的方式更

我有一个长寿命的服务器应用程序,该应用程序设计为在停机时间最少的情况下运行,例如,24/7操作仅为维护而停止。应用程序必须能够每秒处理数千个请求,因此性能是一个问题

为每个请求提供服务。应用程序的一部分需要知道当前日期是什么,尽管不是时间,但由于第三方API的原因,它必须存储在java.util.date对象中

然而,Date对象的构造成本很高,因此为每个请求创建一个新对象听起来并不明智

在请求之间共享日期对象并每天更新一次意味着在启动时每个服务器工作线程只需要创建一个对象,但如何以安全的方式更新它呢

例如,使用在午夜后运行的ScheduledExecutorService可以增加日期,但会在混合中引入线程同步:日期对象现在在主线程和ScheduledExecutorService生成以运行更新任务的线程之间共享

同步两个线程会带来另一个性能问题,因为在被服务的数千个请求之间,共享资源可能会发生争用。每天执行一次更新线程不那么令人担忧,因为它每天只发生一次,不像我们每天要服务的数百万个请求


因此,我的问题是,哪种最有效的方法可以确保应用程序始终知道当前日期,即使连续运行数周也如此?

可以避免同步开销。如果有单个线程执行请求,则可以在同一线程上执行任务以更新日期,而无需任何同步开销。如果有多个线程,那么同样的想法也可以通过将日期字段设置为本地线程并在每个线程中分别更新来应用。

可以避免同步开销。如果有单个线程执行请求,则可以在同一线程上执行任务以更新日期,而无需任何同步开销。如果有多个线程,那么同样的想法也可以通过将日期字段设置为本地线程并在每个线程中分别更新它来应用。

我假设您谈论的昂贵构造函数是new date,它调用System.currentTimeMillis。简单的解决方法是使用newdatelong,使用存储在volatile字段中的值。然后,外部线程可以在适当的时间更新此字段,其他线程将根据此更新的值创建其日期对象


编辑:虽然当前的问题似乎是过早的优化,但System.currentTimeMillis有时可能是瓶颈。如果您处于这种情况,请检查此链接:

我假设您谈论的昂贵构造函数是new Date,它调用System.currentTimeMillis。简单的解决方法是使用newdatelong,使用存储在volatile字段中的值。然后,外部线程可以在适当的时间更新此字段,其他线程将根据此更新的值创建其日期对象


编辑:虽然当前的问题似乎是过早的优化,但System.currentTimeMillis有时可能是瓶颈。如果您处于这种情况,请检查此链接:

不要为此优化而烦恼。它将没有可测量的效果。浪费时间。

不要为这种优化而烦恼。它将没有可测量的效果。浪费时间。

我强烈建议您使用。缓存库具有良好的并发性支持,它提供了几种解决问题的替代方法

一种方法是,如果你的用例可以接受过时的日期,例如新的一天的前100秒,如果你的应用程序仍然认为它是前一天,你可以使用

LoadingCache<Object, Date> tDateCache 
    = CacheBuilder.newBuilder()
                  .maximumSize(1)
                  .expireAfterWrite(100, TimeUnit.SECONDS)
                  .build( new CacheLoader<Object, Date>() {
                              public Date load(Object object) {
                                     return new Date();
                                     }
                              });
使用tDateCache.gettDateCache访问缓存的日期。expireAfterWrite100,TimeUnit.SECONDS参数将导致缓存每100秒自动刷新一次


您还可以有一个监视线程在每次检测到日期滚动时自动调用Cache.invalidateAll,这将导致重新调用缓存加载程序的加载方法并创建新的日期。无需担心并发性,库将为您处理该问题。

我强烈建议您使用。缓存库具有良好的并发性支持,它提供了几种解决问题的替代方法

一种方法是,如果你的用例可以接受过时的日期,例如新的一天的前100秒,如果你的应用程序仍然认为它是前一天,你可以使用

LoadingCache<Object, Date> tDateCache 
    = CacheBuilder.newBuilder()
                  .maximumSize(1)
                  .expireAfterWrite(100, TimeUnit.SECONDS)
                  .build( new CacheLoader<Object, Date>() {
                              public Date load(Object object) {
                                     return new Date();
                                     }
                              });
使用tDateCache.gettDateCache访问缓存的日期。expireAfterWrite100,TimeUnit.SECONDS参数将导致缓存自动刷新 每100秒一次


您还可以有一个监视线程在每次检测到日期滚动时自动调用Cache.invalidateAll,这将导致重新调用缓存加载程序的加载方法并创建新的日期。不必担心并发性,库会为您处理的。

@chrisbunney,这个帖子的一些答案建议使用特殊用途的并发类,但是如果您确实需要按照最初的要求缓存日期,那么您只需要一件事:volatile关键字

如果需要原子检查和交换操作,AtomicReference很好,但在本例中,您没有检查任何东西。您只是将引用设置为一个新值,并且希望该值对所有线程都可见。这就是volatile所做的

如果要修改现有对象的内部状态,则可能需要锁定。或者,如果您要读取现有日期的值,根据该值进行一些计算,并生成一个新的日期对象,那么同样需要某种类型的锁定或类似AtomicReference的东西。但你没有这样做;同样,您只替换引用,而不考虑其以前的值


通常,如果只有一个线程替换一个值,而其他线程只读取该值,那么volatile就足够了。不需要其他并发控制。或者,如果您有多个线程可以替换一个值,但它们只替换,而不是就地修改,并且它们替换它时不考虑它以前的值,那么,volatile就足够了。其他什么都不需要。

@chrisbunney,这个线程中的一些答案建议使用专用并发类,但是如果您确实需要按照最初的要求缓存日期,那么您只需要一件事:volatile关键字

如果需要原子检查和交换操作,AtomicReference很好,但在本例中,您没有检查任何东西。您只是将引用设置为一个新值,并且希望该值对所有线程都可见。这就是volatile所做的

如果要修改现有对象的内部状态,则可能需要锁定。或者,如果您要读取现有日期的值,根据该值进行一些计算,并生成一个新的日期对象,那么同样需要某种类型的锁定或类似AtomicReference的东西。但你没有这样做;同样,您只替换引用,而不考虑其以前的值


通常,如果只有一个线程替换一个值,而其他线程只读取该值,那么volatile就足够了。不需要其他并发控制。或者,如果您有多个线程可以替换一个值,但它们只替换,而不是就地修改,并且它们替换它时不考虑它以前的值,那么,volatile就足够了。不需要其他任何东西。

这听起来像是过早优化的一个主要例子。每秒数千次的请求都是笑话,对吧?你可以每秒创建数百万个,甚至数十亿个新的日期……这可能是真的,但创建日期对象并不是这个应用程序所做的唯一事情,但对于我来说似乎是一个潜在的问题,因为人们普遍认为创建日期对象是一个相对昂贵的操作。对于我们的用例,在负载下平均响应时间的毫秒级改进是合理的。您的CPU可以在毫秒内完成很多工作。在CPU时间里,一毫秒是永恒的。避免创建单一日期不会为您节省那么多。只需几分钟就可以确定创建日期的速度有多快。。。为什么不试试呢?事实上,在发布这篇文章之后,我写了一个小测试来进一步研究性能。我现在同意这是不必要的,但作为一种假设情况,了解哪些方法是可行的仍然很有趣。这听起来像是过早优化的一个主要例子。每秒数千次的请求都是笑话,对吧?你可以每秒创建数百万个,甚至数十亿个新的日期……这可能是真的,但创建日期对象并不是这个应用程序所做的唯一事情,但对于我来说似乎是一个潜在的问题,因为人们普遍认为创建日期对象是一个相对昂贵的操作。对于我们的用例,在负载下平均响应时间的毫秒级改进是合理的。您的CPU可以在毫秒内完成很多工作。在CPU时间里,一毫秒是永恒的。避免创建单一日期不会为您节省那么多。只需几分钟就可以确定创建日期的速度有多快。。。为什么不试试呢?事实上,在发布这篇文章之后,我写了一个小测试来进一步研究性能。我现在同意这是不必要的,但作为一种假设情况,了解可能的方法仍然很有趣。即使我们永远不会在时间字段上执行读-更新-写类型操作,但我们只会忽略旧值
覆盖它,其他一切都只是读取值,这似乎是一种可行且干净的方法,因为我们永远不会在时间字段上执行读更新写类型操作,当一天过去时,我们只会忽略旧值并覆盖它,其他一切都只是读取值,这似乎是一种可行且干净的方法在编写了一些测试之后,我同意:在我的本地机器上,创建每个日期大约需要0.0007毫秒。尽管我仍然对此感兴趣,这只是一种假设情况。在编写了一些测试之后,我同意:在我的本地机器上,创建每个日期大约需要0.0007毫秒。虽然我仍然对这个假设的情况感兴趣。