You don't / can't notify a specific thread. You call notify()
on a lock object. This wakes up one of the threads1 that is waiting on the lock. In your case, the lock object is a Thread
... which rather confuses the picture. However, see below.
但是你的问题(IllegalMonitorStateException
)发生是因为执行通知的线程(即current线程)不持有锁。当前线程在通知锁时必须持有锁,这是一个(硬)要求。
有关更多详细信息,请阅读 javadocsObject.wait(timeout)
或(例如)这个:http://howtodoinjava.com/core-java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/ http://howtodoinjava.com/core-java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/
1 - If multiple threads are waiting on your lock, one thread is chosen "randomly" by the scheduler. Alternatively notifyAll will wake up all of the waiting threads.
我不会使用Thread
对象作为锁对象。它可能会起作用,但也有可能其他东西(可能是运行时系统中的某些东西)也在锁定/等待/通知Thread
对象。那么事情就会变得非常混乱。
(事实上,阅读javadoc https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#join(long) for Thread.join(long)
!)
最好专门为此目的创建锁对象;例如
private final Object lock = new Object();
另外,编写扩展的课程Thread
通常是一个坏主意。通常最好实施Runnable
接口,实例化它,并将实例作为参数传递给Thread
构造函数;例如
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("Hello world");
}});
t.start();
实施的好处之一Runnable
而不是延伸Thread
是您可以更轻松地使用代码来管理线程生命周期;例如一个ExecutorService
、 fork-join 线程池或经典线程池。
第二个是轻量级线程逻辑可以简洁地实现为匿名类......就像我的示例一样。