如何让线程在通知时最后唤醒?
How do I make a Thread wake up last on notify?
我有多个线程在等待时钟的 notify()。这些线程之一应该在运行之前等待其余线程执行。通常我认为这样做的方法是使用 join() 但在这种情况下线程永远不会死,它们只是 wait() 等待下一个滴答信号。有没有办法确保 Thread "z" 总是在 Threads "a-y" 收到相同的 notify() 之后醒来?
编辑:添加了示例代码
线程 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-th Thread并且该值重置为 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
}
}
正如我已经指出的,如果线程中的执行时间大于两个滴答之间的时间,则此构造将失败。请让我确切知道问题是什么,以便为您提供更合适的答案。
我有多个线程在等待时钟的 notify()。这些线程之一应该在运行之前等待其余线程执行。通常我认为这样做的方法是使用 join() 但在这种情况下线程永远不会死,它们只是 wait() 等待下一个滴答信号。有没有办法确保 Thread "z" 总是在 Threads "a-y" 收到相同的 notify() 之后醒来?
编辑:添加了示例代码
线程 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-th Thread并且该值重置为 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
}
}
正如我已经指出的,如果线程中的执行时间大于两个滴答之间的时间,则此构造将失败。请让我确切知道问题是什么,以便为您提供更合适的答案。