1

我已经看到问题如何确定对象是否被锁定(同步)以便在 Java 中不阻塞?
但我有一个我无法解决的问题。
在我的 Web 应用程序中是刷新数据容器的过程,这可能需要很长时间。强制按时间间隔进行刷新。当然,当一个刷新仍在容器上工作时,另一个不能(不破坏容器中的数据)。
我想使用后台线程来刷新容器。多个后台工作人员可以同时在多个容器上工作(不同的工作人员用于不同的用户会话,每个用户会话在其容器中可以有不同的数据)。
我当然可以synchronize(myContainer)在 worker 中强制任何其他 worker 当前没有更新这个特定的容器。但我更想检查是否有任何工作人员正在处理容器并退出,如果是的话。另外我不想更改容器的代码,所以我不想在容器类中添加 ReentrantLock 并锁定它。
所以工人有MyContainer实例并想确定是否有任何其他工人当前正在刷新这个容器实例。

任何想法如何实现这一目标?

4

3 回答 3

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。

于 2013-06-24T14:20:00.263 回答
1

我会将容器放入ConcurrentLinkedQueue并让工作线程poll进入队列,即

Container container;
while((container = queue.poll()) != null) {
    container.refresh();
}

然后,您有两个选项,具体取决于容器是否在刷新时进行跟踪。

  • 如果它们是,那么您可以offer在刷新后立即将刷新的容器放回队列中。您可以使用if(container.refreshTime < X)警卫来确保您不会在同一时间间隔内刷新容器两次。
  • 如果他们不是,那么你也可以
    • 使用两个ConcurrentLinkedQueues并在它们之间交替:pollonqueue1offer刷新的容器 on queue2,以及什么时候queue1是空的 sleep 直到下一个时间间隔,此时pollonqueue2offer刷新的容器 on queue1
    • 或者,在主线程中保留一个容器数组,offer当工作线程完成刷新所有容器并进入睡眠状态时,容器返回队列。
于 2013-06-24T13:23:40.657 回答
0

如果您需要预先检查对象是否还没有被其他线程锁定,这应该可以使用Thread.holdsLock方法。

如果这还不够,请查看高级锁类。这些锁提供了丰富的功能集(检查是否正在等待锁,尝试超时锁定,可中断锁定等)。他们应该提供足够的功能来解决您的问题。

于 2013-06-24T13:24:55.590 回答