Я хотел применить потоки приостановки / возобновления, используя соответственно wait () / notify (). Я неоднократно пытался решить эту проблему, но не мог, поэтому, пожалуйста, помогите мне и объясните, почему notify (); не делает поток счетчика запускаемым:
public class Suspend {
boolean isSuspend = false;
int counter = 0;
synchronized public void suspend() {
isSuspend = true;
System.out.println("The counter was suspended!");
}
synchronized public void resume() {
isSuspend = false;
System.out.println("The counter was resumed :)");
notify();
}
public static void main(String[] args) {
Thread.currentThread().setName("Main Thread");
Suspend suspend = new Suspend();
Thread counterThread = new Thread(new Runnable() {
synchronized public void run() {
while(!suspend.isSuspend) {
System.out.println(suspend.counter++);
try { Thread.sleep(1000); }
catch (InterruptedException e) {}
}
try {
while(suspend.isSuspend)
wait();
}
catch (InterruptedException e) {}
}
}, "Counter Thread");
Thread suspendResumeThread = new Thread(new Runnable() {
synchronized public void run() {
while(true) {
try {
Thread.sleep(5000);
suspend.suspend();
Thread.sleep(5000);
suspend.resume();
} catch (InterruptedException e) {}
}
}
}, "Suspend/Resume Thread");
counterThread.start();
suspendResumeThread.start();
}
}
Результат выглядит следующим образом:
0
1
2
3
4
The counter was suspended!
The counter was resumed :)
The counter was suspended!
The counter was resumed :)
... and so on.
Ваш первый поток ждет одну секунду, поэтому он напечатает 5 раз, прежде чем второй приостановит «блокировку», так что цикл первого потока прервется. Поскольку вы просто вызываете wait () после notify (), код будет возобновлен, но не будет кода для выполнения после, правильным будет вызвать wait () внутри цикла while и изменить его на while (true) с некоторым условием прерывания внутри.
@MadProgrammer Спасибо за ваш комментарий, я пробовал как volatile, так и AtomicBoolean, но, к сожалению, это не работает.
@MarcosVasconcelos Спасибо за ваш комментарий, я пробовал следующее, но это не работает: while (true) {try {if (! Suspend.isSuspend) {System.out.println (suspend.counter ++); попробуйте {Thread.sleep (1000); } catch (InterruptedException e) {}} еще ждать (); } catch (InterruptedException e) {}}




Взгляните на counterThread, пока он заканчивается при первом изменении флага isSuspend.
Думаю, вам нужно что-то вроде этого:
public class Suspend {
volatile boolean isSuspend = false;
int counter = 0;
synchronized public void suspend() {
isSuspend = true;
System.out.println("The counter was suspended!");
}
synchronized public void resume() {
isSuspend = false;
System.out.println("The counter was resumed :)");
notify();
}
public static void main(String[] args) {
Thread.currentThread().setName("Main Thread");
Suspend suspend = new Suspend();
Thread counterThread = new Thread(new Runnable() {
synchronized public void run() {
while(true){
while(!suspend.isSuspend) {
System.out.println(suspend.counter++);
try { Thread.sleep(1000); }
catch (InterruptedException e) {}
}
try {
while(suspend.isSuspend)
wait();
}catch (InterruptedException e) {}
}
}
}
}, "Counter Thread");
Thread suspendResumeThread = new Thread(new Runnable() {
synchronized public void run() {
while(true) {
try {
Thread.sleep(5000);
suspend.suspend();
Thread.sleep(5000);
suspend.resume();
} catch (InterruptedException e) {}
}
}
}, "Suspend/Resume Thread");
counterThread.start();
suspendResumeThread.start();
}
В конце концов, вам нужно также использовать ключевое слово volatile для общих переменных.
Обновлено: я вставил неправильный код, извините
Спасибо за это важное замечание: ** вам также нужно использовать ключевое слово volatile для общих переменных **. Но ваш код не работает, и поток счетчика на этом не заканчивается. Согласно отладчику, статус counterThread - «ожидает: приостановить $ 1 (id = 19)».
Правда, я не заметил отсутствия объекта synchronized on suspend, но в любом случае вам нужно дополнительное while (true)
Проблема в этих строках:
while (suspend.isSuspend)
wait();
}
в вашем counterThread Runnable.
Вы ждете на Runnable, а не на объекте suspend
Вам нужно выполнить синхронизацию на suspend и вызвать wait () на suspend:
synchronized (suspend) {
while (suspend.isSuspend)
suspend.wait();
}
}
Кроме того, ваши методы run не нуждаются в синхронизации.
Большое спасибо, мистер Йоханнес Кун, действительно, ваш код верен на 100%.
Цикл whileдолжен находиться внутри синхронизированного блока или это не потокобезопасный. Вся суть wait() в том, что это атомарная операция, но только при удержании блокировки.
Собственно, если suspend.isSuspended - это volatile, то синхронизировать его не нужно.
boolean isSuspend = false;, вероятно, должен быть энергозависимым или использовать вместо негоAtomicBoolean