如果另一个线程在同一个监视器上阻塞 / 等待,是否可以从一个线程(比如锁定监视器对象的线程)判断?
示例场景 -
“收集器”线程从共享对象读取数据,而 “updater”线程可能被阻塞并等待收集 结束。我希望收藏家知道他什么时候结束 收集,可能的数据更新正在等待产生 收集的数据可能已经无效。
在我的情况下,收集可能是一项耗时的操作,而且在下一阶段,“收集器”线程会分析数据一段时间,这在数据无效的许多情况下可能是冗余操作。
答案 0 :(得分: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();
}
}
}
无论您如何操作,您都需要使用其他机制来考虑新数据更新,而不是检查所有线程的阻塞状态。
答案 1 :(得分:3)
如果您使用java.util.concurrent.locks
框架,可以获取此信息,ReentrantLock类具有以下方法:
Collection<Thread> getQueuedThreads()
- 返回包含可能正在等待获取此锁的线程的集合
Collection<Thread> getWaitingThreads(Condition condition)
- 返回一个集合,其中包含可能正在等待与此锁定关联的给定条件的那些线程。
答案 2 :(得分:0)
一个基本解决方案:添加二进制标志和另一个监视器对象:
volatile boolean haveUpdate = false;
final Object updateMonitor = new Object();
当更新程序线程有新更新时,将haveUpdate
设置为 true ,然后再在数据监视器上进行同步。在数据同步块中的任何位置将其设置回 false (它是唯一可以访问数据的线程)。
收集线程可以定期检查值,如果 true 则中断。当收集线程中断时,它们应该调用updateMonitor.wait()
,然后循环返回再次收集。当更新程序线程离开数据同步块时,它应该调用updateMonitor.notifyAll()
。
现在,当任何收集线程看到有正在进行或正在进行的更新时,它将停止,等待它完成,然后再次启动。