Как сделать так, чтобы Тема просыпалась последней при уведомлении?
У меня есть несколько потоков, ожидающих уведомления () от тиковых часов. Один из этих потоков должен дождаться выполнения остальных, прежде чем он запустится. Обычно я считаю, что способ сделать это - использовать join(), но в этом случае потоки никогда не умирают, они просто ждут () следующего тикового сигнала. Есть ли способ обеспечить, чтобы поток "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.
1 ответ
Если я правильно понимаю, есть 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
}
}
Как я уже указывал, эта конструкция потерпит неудачу, если время выполнения в потоке будет больше, чем время между двумя тиками. Пожалуйста, дайте мне точно знать, в чем проблема, чтобы дать вам более подходящий ответ.