Java wait () и notify () не работают должным образом - PullRequest
0 голосов
/ 09 июня 2019

Я новичок в Java Multithreading и застрял в одной проблеме.

public class WaitAndNotify {

   private static List<String> strings = Collections.synchronizedList(new ArrayList<>());

   public static void main(String[] args) {
       new Operator().start();
       new Machine().start();
   }

   // Operator thread
   static class Operator extends Thread {
       @Override
       public void run() {
           Scanner scanner = new Scanner(System.in);
           while (true) {
               System.out.println("Operator is working");
               synchronized (strings) {
                   strings.add(scanner.nextLine());
                   strings.notify();
                   System.out.println("Notifying to machine");
               }
               try {
                   sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
       }
   }

   // Machine thread
   static class Machine extends Thread {
       @Override
       public void run() {
           while (strings.isEmpty()) {
               synchronized (strings) {
                   try {
                       strings.wait();
                       System.out.println("Machine is waiting");
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println(strings.remove(0));
               }
           }
       }
   }
}

У меня есть оператор и машина threads.Я запускаю каждый поток, и когда я пишу что-то в консоли, он должен notify машина, и машина должна распечатать это.Это работает, но иногда машина не звонит.Когда я удаляю часть thread.sleep() после notify, она вообще не работает.

Консоль, когда все работает нормально.

Operator is working
Hi...               // That's our message that we write in console
Notifying to machine
Machine is waiting
Hi...              // Machine printed our message successfully after 1 second
Operator is working

Что произойдет, если удалить часть thread.sleep().

Operator is working
Hi...             // That's our message that we write in console
Notifying to machine
Operator is working

Как видите, машина не работает.Я не знаю, может быть, он заблокирован или что-то еще.Так может кто-нибудь объяснить мне, почему аппарат не печатает наше сообщение, когда thread.sleep() удален?

1 Ответ

1 голос
/ 09 июня 2019

Когда вы отключаете режим сна, машина должна ждать, пока не будет снята блокировка, после

System.out.println("Notifying to machine");

После этой линии и машина, и оператор борются за замок. Если оператор подгоняет машину к ней, он запросит ввод во второй раз, прежде чем машина что-либо напечатает. После этой точки аппарат сможет печатать только один раз, а затем выйдет из цикла while. Поскольку он удаляет только 1 элемент из массива, массив всегда будет иметь более 0 элементов.

Следующая версия отлично работает

    static class Operator extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("Operator is working");
            synchronized (strings) {
                System.out.println("Notifying to machine1");
                strings.add(scanner.nextLine());
                strings.notify();
                System.out.println("Notifying to machine2");
                try {
                    strings.wait();
                }catch (Exception ex){}
            }
        }
    }
}

// Machine thread
static class Machine extends Thread {
    @Override
    public void run() {
        while (strings.isEmpty()) {
            System.out.println("strings is empty");
            synchronized (strings) {
                strings.notify();
                try {
                    System.out.println("Machine is waiting 1");
                    strings.wait();
                    System.out.println("Machine is waiting 2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(strings.remove(0));
            }
        }
    }
}
...