3

Is there a way to tell from one thread (say the one which locks a monitor object) if another thread is blocked / waiting on same monitor?

Example scenario -

a "collector" thread reads data from a shared object, while the "updater" thread might be blocked and waiting for the collection to end. I would like the collector to know that when he finishes collecting, a possible data update is pending which yield the collected data might already be invalid.

In my case collecting might be a time consuming operation, and also in the next stage the "collector" thread analyzes the data for some more time, which might be a redundant operation in many cases where the data is invalid.

4

3 回答 3

3

如果你使用java.util.concurrent.locks框架,你可以得到这个信息,ReentrantLock 类有这样的方法:

Collection<Thread> getQueuedThreads()- 返回一个集合,其中包含可能正在等待获取此锁的线程

Collection<Thread> getWaitingThreads(Condition condition)- 返回一个集合,其中包含可能正在等待与此锁关联的给定条件的那些线程。

于 2013-07-25T14:00:03.617 回答
3

有没有办法从一个线程(比如锁定监视器对象的线程)判断另一个线程是否在同一个监视器上阻塞/等待?

不,不是来自对象本身。正如@Evgeniy 所提到的,您可以使用其他java.util.concurrent.locks.*允许您查看排队成员的类,但不能从某种synchronized (lock)对象监视器中查看。

我希望收集者知道,当他完成收集时,可能的数据更新正在等待处理,这导致收集的数据可能已经无效。

有一个更新怎么样,BlockingQueue以便收集器可以检查队列并查看它是否为非空。更新线程将只是向 中添加Update信息,BlockingQueue而收集器会将更新出列并进行调整。然后它可以检查队列的长度并决定是否需要进入分析模式。

private BlockingQueue<Update> updateQueue = new LinkedBlockingQueue<Update>();
...
// called by the updater thread(s)
public void updateData(Update update) {
    updateQueue.put(update);
}
// called by the collector
public void collect() {
    while (!Thread.currentThread().isInterrupted()) {
        Update update = updateQueue.take();
        updateValues(update);
        if (updateQueue.isEmpty()) {
           analyzeData();
        }
    }
}

不管你怎么做,你都需要使用其他机制来考虑新的数据更新,而不是检查所有线程的阻塞状态。

于 2013-07-25T13:33:07.117 回答
0

一个基本解决方案:添加一个二进制标志和另一个监视器对象:

volatile boolean  haveUpdate = false;
final Object      updateMonitor = new Object();

当更新程序线程有新更新时设置haveUpdatetrue,然后在数据监视器上同步。在数据同步块(它是唯一可以访问数据的线程)中的任何点将其设置回false 。

收集线程可以定期检查该值,如果为true则中断。当收集线程中断时,它们应该调用updateMonitor.wait(),然后循环返回以再次收集。当更新线程离开数据同步块时,它应该调用updateMonitor.notifyAll().

现在,当任何收集线程看到有更新即将到来或正在进行时,它将停止,等待它完成,然后重新启动。

于 2013-07-25T15:35:25.093 回答