Java wait()和notify()不能正常工作

时间:2019-06-09 13:51:49

标签: java multithreading java-threads

我是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 个答案:

答案 0 :(得分:1)

当您消除睡眠时,机器必须等待直到解除锁定为止

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));
            }
        }
    }
}