我是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));
}
}
}
}
}
我有操作员和机器threads
。我启动每个线程,当我在控制台中编写内容时,它必须notify
机器,机器必须打印它。这是有效的,但有时机器不是调用。当我在notify
后移除thread.sleep()
部分时,它根本不起作用。
一切正常时的控制台。
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()
时不打印我们的消息?
当您删除睡眠时,机器必须等到锁定被释放,这是之后
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));
}
}
}
}