Использование wait() может не работать так, как вы ожидаете. Ожидание/уведомление построено как простая реализация контекста параллельного программирования sempaphore (как объекта с широким экраном экземпляра). Вызов уведомления() из любой другой нити, не блокирующей монитор экземпляра объекта нити, не будет работать, см. Java Wait and Notify: IllegalMonitorStateException
Вы можете легко достичь своей цели, регулярно проверяя флаг подвески и просто подождите немного, если ваша нить ничего не должен делать:
public class SuspendDemo implements Runnable {
public Thread t;
private final String threadName;
boolean suspended = false;
SuspendDemo(final String name){
threadName = name;
System.out.println("Creating " + threadName);
}
@Override
public void run() {
System.out.println("Running " + threadName);
try {
while (true) {
System.out.println("Thread: " + threadName);
// Let the thread sleep for a while.
Thread.sleep(300);
while(suspended) {
System.out.println("suspended");
Thread.sleep(50);
}
}
} catch (final InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start() {
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread (this, threadName);
t.start();
}
}
void suspend() {
suspended = true;
}
void resume() {
suspended = false;
notify();
}
public static void main(final String[] args) throws InterruptedException {
final SuspendDemo R1 = new SuspendDemo("Thread-1");
R1.start();
R1.suspend();
Thread.sleep(500);
R1.resume();
}
}
Результирующая:
> Creating Thread-1
> Starting Thread-1
> Running Thread-1
> Thread: Thread-1
> suspended
> suspended
> suspended
> suspended
> Thread: Thread-1
> Thread: Thread-1
> Thread: Thread-1
приостановить флаг является родным булево, поэтому пишу это атомарная операция, поэтому вы можете обойтись без синхронизации на что-нибудь. Предлагаю полностью понять параллельное программирование и модель параллелизма , которую использует Java, перед использованием синхронизации. Я обнаружил, что использование synchronize (this) блокирует сложность в обслуживании и подвержено ошибкам.
Следующий пример решает проблему с ожидания() и notifyAll(). Обратите внимание на использование синхронизированных методов для блокировки монитора объекта потока вместо блоков synchronize (this).
public class SuspendDemo implements Runnable {
public Thread t;
private final String threadName;
boolean suspended = false;
SuspendDemo(final String name){
threadName = name;
System.out.println("Creating " + threadName);
}
@Override
public void run() {
System.out.println("Running " + threadName);
try {
while (true) {
System.out.println("Thread: " + threadName);
// Let the thread sleep for a while.
Thread.sleep(300);
work();
}
} catch (final InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
synchronized protected void work() throws InterruptedException {
while(suspended) {
System.out.println("suspended");
wait();
System.out.println("resumed");
}
}
public void start() {
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread (this, threadName);
t.start();
}
}
synchronized void suspend() {
suspended = true;
notifyAll();
}
synchronized void resume() {
suspended = false;
notifyAll();
}
public static void main(final String[] args) throws InterruptedException {
final SuspendDemo R1 = new SuspendDemo("Thread-1");
R1.start();
R1.suspend();
Thread.sleep(500);
R1.resume();
}
}
Функция 'suspend' не синхронизирована. Таким образом, ваш 'synchronized (this)' блок на самом деле ничего не делает. Только один поток вызывает 'run' в любом случае, поэтому вы не синхронизируете его ни с чем другим. Вам также нужно вызвать 'notify' в' suspend', иначе поток не проснется. –