Приостановить Темы Возобновления: Java

Когда я запускаю этот код, он отображает следующий вывод:

One : 15 Two : 15 One : 14 Two : 14 Two : 13 One : 13 Two : 12 One : 12 One : 11 Two : 11 Thread 1 suspended Two : 10 Two : 9 Two : 8 Two : 7 Two : 6 Thread 1 resumed Thread 2 suspended Thread 2 resumed

Вывод не продолжается до конца, то есть One:1 Two:1 Не выполняется ли метод myresume класса NewThread1? В чем причина этого?

Ниже приведен код NewThread1:

class NewThread1 implements Runnable{
String name;
Thread t;
boolean suspendFlag;

NewThread1(String threadname){
    name = threadname;
    t = new Thread(this, name);
    suspendFlag = false;
    t.start();
}

@Override
public void run(){
    try{ 
         for(int i=15; i>0; i--){
             System.out.println(name+ " : " +i);
             Thread.sleep(200);
                synchronized(this){
                    while(suspendFlag){
                        wait();
                    }
                }
        }
    }catch(InterruptedException e){
        System.out.println("New thread1 Interrupted");
    }
}
synchronized void myresume(){
    suspendFlag = false;
}
void mysuspend(){
    suspendFlag = true;
}
}        

Ниже приведен код NewThread1:(здесь определен метод main())

public class Suspend_ResumeThreads {
public static void main(String args[]){
    NewThread1 ob1 = new NewThread1("One ");
    NewThread1 ob2 = new NewThread1("Two ");

    try{
        Thread.sleep(1000);
        ob1.mysuspend();
        System.out.println("Thread 1 suspended");
        Thread.sleep(1000);
        ob1.myresume();
        System.out.println("Thread 1 resumed");

        ob2.mysuspend();
        System.out.println("Thread 2 suspended");
        Thread.sleep(1000);
        ob2.myresume();
        System.out.println("Thread 2 resumed");

    }catch(InterruptedException e){
        System.out.println("Main Interrupted");
    }

    try{
        ob1.t.join();
        ob2.t.join();
    }catch(InterruptedException e){
        System.out.println("Main interrupeted in join()");
    }
System.out.println("Main exiting..");    
}
}

1 ответ

Решение

Использование notifyAll прервать wait(): положил

this.notifyAll();

в ваш myresume() функция. Но всегда будьте готовы к тому, что это уведомление будет потеряно; в частности, когда ни один поток в данный момент не ожидает, он все равно будет успешным.

Убедись, что ты synchronize/wait/notify на том же объекте. Распространенной ошибкой является синхронизация на this и не осознавать, что в контексте анонимного внутреннего класса, this может быть что-то другое. И что еще хуже, это может измениться при рефакторинге кода! Лучше всего иметь Object lock = new Object(); где-то и всегда synchronize(lock) ... lock.wait(); ... lock.notifyAll(); чтобы избежать таких ошибок программирования (и рефакторинга).

Если вы не делаете suspendFlagvolatileтакже существует вероятность того, что разные потоки увидят разные значения этого поля (если это не так volatileпотоки могут хранить локальную копию в кэше процессора). Таким образом, это также может быть хорошо сделать mysuspend синхронизируется тоже.

В некоторых случаях вам может потребоваться переключиться на более продвинутую синхронизацию, такую ​​как java.util.concurrent.locks.Lock и java.util.concurrent.Semaphore.

Другие вопросы по тегам