Java并发-监视器被阻止了吗?

Java并发-监视器被阻止了吗?,java,multithreading,synchronization,Java,Multithreading,Synchronization,有没有办法从一个线程(比如锁定监视器对象的线程)判断另一个线程是否在同一个监视器上被阻止了 示例场景- “收集器”线程从共享对象读取数据,而 “updater”线程可能已被阻止,正在等待集合恢复 结束。我想让收藏家知道,当他完成 正在收集,可能的数据更新正在挂起,这将产生 收集的数据可能已经无效 在我的例子中,收集可能是一个耗时的操作,而且在下一个阶段,“收集器”线程会对数据进行更长时间的分析,在许多数据无效的情况下,这可能是一个冗余操作 有没有办法从一个线程(比如锁定监视器对象的线程)判断另一

有没有办法从一个线程(比如锁定监视器对象的线程)判断另一个线程是否在同一个监视器上被阻止了

示例场景-

“收集器”线程从共享对象读取数据,而 “updater”线程可能已被阻止,正在等待集合恢复 结束。我想让收藏家知道,当他完成 正在收集,可能的数据更新正在挂起,这将产生 收集的数据可能已经无效

在我的例子中,收集可能是一个耗时的操作,而且在下一个阶段,“收集器”线程会对数据进行更长时间的分析,在许多数据无效的情况下,这可能是一个冗余操作

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

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

我想让催收员知道,当他完成收集时,可能的数据更新正在等待,这可能导致收集的数据可能已经无效

阻塞队列
更新如何,这样收集器就可以检查队列并查看它是否为非空。更新程序线程只需将
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();
        }
    }
}
private BlockingQueue updateQueue=new LinkedBlockingQueue();
...
//由更新程序线程调用
公共无效更新数据(更新){
updateQueue.put(更新);
}
//催收员呼叫
公开募捐{
而(!Thread.currentThread().isInterrupted()){
Update Update=updateQueue.take();
更新值(更新);
if(updateQueue.isEmpty()){
分析数据();
}
}
}

无论您如何操作,您都需要使用其他机制来解释新的数据更新,而不是检查所有线程的阻塞状态。

如果您使用
java.util.concurrent.locks
框架,ReentrantLock类具有以下方法,则可以获得此信息:

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


集合getWaitingThreads(条件条件)
-返回一个集合,其中包含可能正在等待与此锁关联的给定条件的线程

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

volatile boolean  haveUpdate = false;
final Object      updateMonitor = new Object();
当更新程序线程在数据监视器上同步之前有一个新的更新时,将
haveUpdate
设置为true。在数据同步块中的任意点将其设置回false(在该块中,它是唯一可以访问数据的线程)

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


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

事实上,我的机制确实使用了
阻塞队列。检查它的长度是一个有趣的想法!我愿意接受你的回答,因为你的回答更具帮助性和建设性,但当它说不可能实现最初的目标时,我不能接受,而从@Evgenniy的回答来看,很明显有。请编辑你的答案。我已经调整了我的答案@Elist。我曾考虑过提及其他
Lock
类,但我不想混淆我的答案。:-)谢谢,看起来正是我想要的!我试试看。