Напечатать последовательность чисел с помощью двух чередующихся потоков


Я написал программу, которая создает 2 новых потока и разделяет Общий объект блокировки для того чтобы напечатать номера альтернативно. Хотел бы знать, если этот подход использовать wait() и Notify() является правильным?

Основной Класс

public class MyMain {
public static void main(String[] args) {
MyThread1 obj = new MyThread1();
Thread thread1 = new Thread(obj);
Thread thread2 = new Thread(obj);

thread1.setName("t1");
thread2.setName("t2");

thread1.start();
thread2.start();

}
}

Класс Thread

public class MyThread1 implements Runnable{
int i = 0;
@Override
public synchronized void run() {
    while(i<10)
    {
        if(i%2==0)
        {   
try{
                notify();
                System.out.println(Thread.currentThread().getName()+" prints "+i);
                i++;
                wait();

             }catch(Exception e){ e.printStackTrace(); }
        }else
        {
            try{
                notify();
                System.out.println(Thread.currentThread().getName()+" prints "+i);
                i++;
                wait();
            }catch(Exception e){ e.printStackTrace(); }
        }
    }
}
}

Может быть лучше использования wait() и Notify() вместо того, чтобы использовать его в если условиях?



1526
1
задан 4 апреля 2018 в 09:04 Источник Поделиться
Комментарии
1 ответ

Я не уверен, что вы ожидаете от написания if-else построить где if и else блок содержит точно такой же код. Ваш run() способ эффективно эквивалентно следующему:

public synchronized void run() {
while (i < 10) {
try {
notify();
System.out.println(Thread.currentThread().getName() + " prints " + i);
i++;
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Кроме этого, использование notify() и wait() выглядит нормально. Однако, есть такое явление называется "ложные пробуждения", которое означает, что поток может быть разбужен без всякой видимой причины на всех. Это очень маловероятно, но теоретически возможно, что один из двух потоков ложно проснулся после того, как он входит в состояние ожидание, но, прежде чем другой поток получает блокировку на obj, что может повлечь за один поток печати два последовательных числа, если поток, который был ложно проснулся вновь получает блокировку. Вы можете взглянуть на это.

Кроме того, ваша программа никогда не завершается. Вы можете исправить это путем вызова notify() или notifyAll() после while петли.

3
ответ дан 4 апреля 2018 в 10:04 Источник Поделиться