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

Java wait()和notify()工作不正常,java,multithreading,java-threads,Java,Multithreading,Java Threads,我是Java多线程方面的新手,我遇到了一个问题 public class WaitAndNotify { private static List<String> strings = Collections.synchronizedList(new ArrayList<>()); public static void main(String[] args) { new Operator().start(); new Machine

我是Java多线程方面的新手,我遇到了一个问题

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));
               }
           }
       }
   }
}
如果删除了
thread.sleep()
部分,会发生什么情况

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

正如你们所看到的,机器不工作了。我不知道可能是锁上了还是别的什么。所以,有人能向我解释一下,当
thread.sleep()
被删除时,机器为什么不打印我们的消息吗?

当您删除sleep时,机器必须等待锁被释放,这是在

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

操作员只是在等待输入。确实有更好、更高级的方法来实现同步。我建议使用
阻塞队列
,它基本上可以免费提供您想要的行为。如果没有睡眠,操作员可以多次获得锁,而不给机器一个机会。如果发生这种情况,数组将至少有2个元素。如果机器获得锁,它将打印一次,然后返回,因为
而(strings.isEmpty())
将返回false确定谢谢。我懂一点,但不完全懂
    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));
            }
        }
    }
}