我见过问题How do determine if an object is locked (synchronized) so not to block in Java?
但我有问题,我无法找到解决方案
在我的Web应用程序中是刷新数据容器的过程,这可能需要很长时间。刷新是在时间间隔内进行的。当然,当一个刷新仍然在容器上工作时,另一个不能(不要破坏容器中的数据)
我想使用后台线程来刷新容器。多个后台工作人员可以同时在多个容器上工作(不同的工作人员用于不同的用户会话,每个用户会话可以在其容器中具有不同的数据)。
当然,我可以在worker中执行synchronize(myContainer)
以强制任何其他worker当前没有更新此特定容器。但我宁愿检查是否有工人正在处理容器并退出,如果是的话。另外我想不要更改容器的代码,所以我不想在容器类中添加ReentrantLock并锁定它。
因此,worker具有MyContainer
实例,并且想要确定当前是否正在刷新此容器实例。
任何想法如何实现?
答案 0 :(得分:2)
使用AtomicBoolean
,将此代码放入MyContainer
类:
AtomicBoolean isRefreshing = new AtomicBoolean(false);
void refresh() {
if ( isRefreshing.compareAndSet( false, true)) {
try {
// refresh
} finally {
isRefreshing.set( false);
}
}
}
如果你无法触摸MyContainer,可能会创建一个包含AtomicBoolean和MyContainer实例的RefreshWrapper。
答案 1 :(得分:1)
我会将容器放在ConcurrentLinkedQueue中并让工作线程poll
成为队列,即
Container container;
while((container = queue.poll()) != null) {
container.refresh();
}
然后,您有两个选项,具体取决于容器在刷新时是否正在跟踪。
offer
刷新容器重新进入队列。您可以使用if(container.refreshTime < X)
防护,以确保您不会在同一时间间隔内刷新容器两次。ConcurrentLinkedQueues
并在它们之间切换:poll
queue1
和offer
queue2
上的刷新容器,queue1
时清空直到下一个时间间隔,此时poll
queue2
和offer
queue1
上的刷新容器。 offer
容器返回队列。答案 2 :(得分:0)
如果您需要预先检查该对象是否尚未被某个其他线程锁定,则可以使用Thread.holdsLock方法进行此操作。
如果这还不够,请查看advanced lock classes。这些锁提供了丰富的功能集(检查等待锁定,尝试锁定超时,锁定中断等)。他们应该提供足够的功能来解决你的问题。