如何让线程在通知时最后唤醒?

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
    }
}

正如我已经指出的,如果线程中的执行时间大于两个滴答之间的时间,则此构造将失败。请让我确切知道问题是什么,以便为您提供更合适的答案。