我是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()
时机器不打印我们的消息?
答案 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));
}
}
}
}