一:线程的通信:
首先我们来看一个例子:
使用两个线程打印1-100.线程1,线程2 交替打印
此程序设计到三个方法:
wait():
一旦执行次方法,当前线程就进入阻塞状态,并释放同步监视器(锁)。
notify():
一旦执行此方法,就会唤醒wait的一个线程。如果多个线程被wait,就唤醒优先级高的线程。
nodifyAll():
一旦执行此方法,就会唤醒所有被wait的线程。
说明:
1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器。否则,会出现IllegalMonitorStateException异常
3.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中。
sleep() 和 wait() 的异同?
1.相同点:一旦执行此方法,就可以使得当前线程进入阻塞状态。
2.不同点:
- ①两个方法声明的位置不同:Thread类中声明sleep(),object类中声明wait();
- ②调用的场景不同:sleep()可以在任何需求的场景下调用。wait()必须使用在同步代码块或同步方法中。
- ③关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,调用wait()时线程阻塞,但会释放同步监视器;而sleep()不会。
二:生产者消费者问题(线程通信的应用):
生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者,如果生产者视图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了在通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了在通知消费者来取走产品。
涉及的几个问题:
1.是否是多线程问题?是,生产者线程,消费者线程
2.是否有共享数据?是,店员(或产品)
3.如何解决线程的安全问题?同步机制,三种方法
4.是否涉及线程的通信?是
此程序的同步监视器(锁):clerk对象。
- 生产者在调用生产函数produceProduct()的时候,消费者无法调用消费函数consumeProduct()。因为他们是同一个同步监视器clerk对象。
- 生产者生产一个产品后阻塞wait(),并释放锁,而后消费者开始消费产品,消费完毕后,唤醒notify()生产者,而后消费者阻塞wait(),并释放锁。