这节课我们来填坑,讲讲wait,notify,notifyAll,这三个方法主要用于线程间通信。
先来看API文档怎么写的:
看到这里的人先暂停一下,把上面的截图过一遍。
下面来讲讲怎么用:
Demo:
/**
* 线程间通信教学
*/
public class ThreadCommunicationTeach {
public static void main(String[] args) throws InterruptedException {
//纯粹的监视器
//一个监视器可以监视多个线程,但是一个线程在同一时间只能有一个监视器
Object listener = new Object();
Thread thread1 = new MyThread2(listener,"线程1");
Thread thread2 = new MyThread2(listener,"线程2");
thread1.start();
thread2.start();
while (true)
{
if (thread1.getState() == Thread.State.WAITING)
{
System.out.println("线程1进入阻塞状态");
Thread.sleep(1000);
//这里没加同步
synchronized (listener)
{
listener.notify();
}
}
if (thread2.getState() == Thread.State.WAITING)
{
System.out.println("线程2进入阻塞状态");
Thread.sleep(1000);
synchronized (listener)
{
listener.notify();
}
}
if (thread1.getState() == Thread.State.TERMINATED && thread2.getState() == Thread.State.TERMINATED)
{
break;
}
}
/**
* 可以看到抛出异常了: IllegalMonitorStateException
*
* 通过以下三种方法之一,线程可以成为此对象监视器的所有者:
*
* 通过执行此对象的同步实例方法。
* 通过执行在此对象上进行同步的 synchronized 语句的正文。
* 对于 Class 类型的对象,可以通过执行该类的同步静态方法。
*
* 说白了就是要加synchronized
* wait和notify以及notifyAll三个方法都必须在同步方法或者同步方法块里
* 否则抛异常IllegalMonitorStateException
*
* 如何保证多线程有序执行?就是用线程间通信。
*
* 接下来说说wait
* wait就是让当前正在运行的线程进入等待状态,并且调用wait方法的对象会成为这个等待线程的监视器
* 一个监视器可以监视多个线程,但一个线程同一时间只能有一个监视器
*
* notify:
* 调用此方法的对象唤醒该对象所监视的所有线程中的一个(随机的)
* 唤醒的意思就是让处于等待状态的线程进入就绪状态
*
* notifyAll:
* 调用此方法的对象唤醒该对象所监视的所有线程
*/
}
}
//瞎取个名字
class MyThread2 extends Thread{
//监视器,用于让本线程进入等待状态(也叫阻塞状态)或唤醒该线程
Object listener;
public MyThread2(Object listener,String name)
{
this.listener = listener;
setName(name);
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
if (i == 2)
{
try {
synchronized (listener)
{
listener.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//这个居然忘记加了,要看下怎么输出的对吧
System.out.println(getName() + ": " + i);
}
}
}