[英]How do I make a Thread wake up last on notify?
我有多个线程正在等待滴答时钟的notify()。 这些线程之一应在运行之前等待其余线程执行。 通常,我相信这样做的方法是使用join(),但是在这种情况下,线程永不消亡,它们只是等待下一个滴答信号。 有没有一种方法可以确保在收到相同的notify()之后,线程“ z”将始终在线程“ ay”之后唤醒?
编辑:例如添加代码
线程1-4:
while(running) {
synchronized(tickSignal){
/*
* Code in this section adds objects to a queue that Thread 5 reads
* It also has other code that must be executed every tick
*/
tickSignal.wait();
}
}
线程5:
while(running) {
synchronized(tickSignal) {
/*
* Code in this section reads all the objects added to the queue by T1-4
* It also has other code that must be executed every tick
*/
tickSignal.wait();
}
}
刻度时钟:
while(running) {
synchronized(tickSignal){
tickSignal.notifyAll();
}
Thread.sleep(1000);
}
还有其他监视tickSignal的线程根本不与线程5交互。
如果我正确理解,则在发出滴答信号时有N个任务要执行。 第N个任务只能在第一个N-1个任务完成后开始。 由于notifyAll()函数以无序方式通知线程,因此您必须稍微扩展代码。
首先,我认为这种建筑不是安全的建筑。 考虑一下在一个线程中执行代码花费超过1秒的情况。 在这种情况下,由于线程尚未到达wait()函数,因此不会在下一个滴答信号处通知该线程。 但是,现在让我们假设这不会发生。
由于第N个任务只能在第一个N-1个任务完成后才能执行,因此它必须等待并在第一个N-1个任务实际完成时得到通知。 为了计算已完成任务的数量,可以使用线程安全的AtomicInteger计数器。 每次任务完成时,计数器都会以1递增。当计数器达到值N-1时 ,它会通知第N个线程并将该值重置为0。
为您提供代码:
// Besides a tickSignal, we also need a finalThreadSignal, which
// will be notified when the first N-1 Threads are finished.
private Object tickSignal = new Object();
private Object finalThreadSignal = new Object();
private AtomicInteger completedThreadsCounter = new AtomicInteger(0);
线程1-(N-1):
while (running) {
synchronized (tickSignal) {
try {
tickSignal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Code
// Task finished
int counter = completedThreadsCounter.incrementAndGet();
if (counter == N-1) {
// Notify Thread N when the first N-1 tasks are finished
synchronized (finalThreadSignal) {
finalThreadSignal.notify();
}
// Reset the finished Threads counter and wait for the next tick signal
completedThreadsCounter.set(0);
}
}
}
线程N:
while (running) {
// Here we synchronize on the signal that will be given when
// the first N-1 Threads are finished
synchronized (finalThreadSignal) {
try {
finalThreadSignal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Execute final Thread code
}
}
正如我已经指出的,如果一个线程中的执行时间大于两次滴答之间的时间,则这种构造将失败。 请让我确切知道问题所在,以便为您提供更合适的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.