Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.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
Java7:在ServletContextListener中实现线程安全的可修改静态对象的最佳方法?_Java_Multithreading_Servlets_Concurrency - Fatal编程技术网

Java7:在ServletContextListener中实现线程安全的可修改静态对象的最佳方法?

Java7:在ServletContextListener中实现线程安全的可修改静态对象的最佳方法?,java,multithreading,servlets,concurrency,Java,Multithreading,Servlets,Concurrency,在Java7Tomcat应用程序中,包含几个简单字符串和数字类型的对象/结构obj经常由多个servlet线程共享读取。每隔n分钟,obj的所有成员都需要同步地、原子地刷新,并且每个servlet线程在读取对象时都必须始终获得更新的值。如果未连接任何客户端,则无需刷新值;但是,假设自上次更新以来至少已经过了n分钟,那么一旦连接完成,就需要在读取对象之前进行更新。更新:我应该提到,目前,obj的一个成员是一个时间戳,指示对象数据何时过期并需要刷新。如果一个解决方案,比如下面评论中建议的Guava

在Java7Tomcat应用程序中,包含几个简单字符串和数字类型的对象/结构obj经常由多个servlet线程共享读取。每隔n分钟,obj的所有成员都需要同步地、原子地刷新,并且每个servlet线程在读取对象时都必须始终获得更新的值。如果未连接任何客户端,则无需刷新值;但是,假设自上次更新以来至少已经过了n分钟,那么一旦连接完成,就需要在读取对象之前进行更新。更新:我应该提到,目前,obj的一个成员是一个时间戳,指示对象数据何时过期并需要刷新。如果一个解决方案,比如下面评论中建议的Guava Cache,已经内置了这个功能,那么就更好了

您将如何在Java7中实现这一点?在这一点上,简单性和“清洁度”比性能更重要,但如果您还想提供针对性能优化的解决方案,请这样做。我有一个想法,可能会也可能不会按照我预期的方式工作,但我想先听听其他的意见。提前感谢。

使用缓存

在上下文侦听器中,执行以下操作:

LoadingCache<String, List<YourObjectType>> myCache = CacheBuilder.newBuilder()
    .expireAfterWrite(60, TimeUnit.MINUTES)
    .build(new CacheLoader<String, List<YourObjecttype>>() {
        public List<YourObjectType> load(String arg) {
            ...
        }
});

然后通过从上下文对象获取myCache属性,在任何地方使用它。

集群中部署的应用程序如何。您是否仍希望在不同VM上运行的应用程序实例之间共享该状态?那么您可能需要某种类型的分布式缓存,如Ehcache或Hazelcast。那么可用性呢?JVM崩溃后数据是否应该保持可用?解决方案仍然是一个外部缓存,但是一个本身[配置为]分布式并且通常[配置为]在可靠的数据存储中具有持久性的缓存我将使用Guava缓存。在servlet上下文侦听器中创建对象,然后您可以在应用程序中的任何位置访问/修改它。@RobbyCornelissen True。我猜外部缓存的想法听起来不错,但后来我意识到这需要多少开销,并改变了我的想法:进一步考虑,在应用程序/虚拟机之间共享数据是没有必要的。如果您需要其他代码,例如关于如何刷新数据和/或如何从servlet使用数据的代码,请告诉我。是的,那太好了。我可以看到expireAfterWrite60,TimeUnit.MINUTES将导致缓存在一小时后过期,但如何使它在过期时自动调用自定义刷新代码?每次有东西放入缓存时都会调用load吗?让我澄清一下:我不一定希望缓存在过期后立即刷新;我需要在下次读取之前刷新它,我认为这是默认行为。但是我如何指定/覆盖刷新行为,以便它调用我的代码来生成要放入缓存的新值?refreshAfterWrite调用重新加载方法,您可以在生成方法中提供该方法:@Yury确保您接受我的答案,如果它对您有用:
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("myCache", myCache);