public class Demo01{
public static void main(String[] args) throws InterruptedException {
var q = new TaskQueue();
var ts = new ArrayList<Thread>();
for (int i=0; i<5; i++) {
var t = new Thread() {
public void run() {
// 执行task:
while (true) {
try {
String s = q.getTask();
System.out.println("execute task: " + s);
} catch (InterruptedException e) {
return;
}
}
}
};
t.start();
ts.add(t);
}
var add = new Thread(() -> {
for (int i=0; i<10; i++) {
// 放入task:
String s = "t-" + Math.random();
System.out.println("add task: " + s);
q.addTask(s);
try { Thread.sleep(100); } catch(InterruptedException e) {}
}
});
add.start();
add.join();
Thread.sleep(100);
for (var t : ts) {
t.interrupt();
}
}
}
class TaskQueue {
Queue<String> queue = new LinkedList<>();
public synchronized void addTask(String s) {
this.queue.add(s);
this.notifyAll();
}
public synchronized String getTask() throws InterruptedException {
while (queue.isEmpty()) {
this.wait();
}
return queue.remove();
}
}
教程这样说道:“内部调用了this.notifyAll()而不是this.notify(),使用notifyAll()将唤醒所有当前正在this锁等待的线程,而notify()只会唤醒其中一个(具体哪个依赖操作系统,有一定的随机性)。这是因为可能有多个线程正在getTask()方法内部的wait()中等待” 。
我有点疑惑的一句话是 “可能有多个线程正在getTask()方法内部的wait()中等待” , 比如A B C 三个线程,A线程进入了 getTask()方法 , 那么 B 和 C 方法就必须在外面等着啊 。
比如A B C 三个线程,A线程进入了 getTask()方法 , 那么 B 和 C 方法就必须在外面等着,A调用this.wait(),A就加入到this的等待房间,并释放锁了,B和C有个就进来了,然后重复A的过程,就这样他们三个都进到 this的等待房间了,addTask中有线程调用this.notifyAll(),那么就去房间里面去叫醒ABC三个线程他们先抢占锁,抢占到了就从this.wait()继续执行。