这节课我们来填坑,讲讲wait,notify,notifyAll,这三个方法主要用于线程间通信。


  先来看API文档怎么写的:

线程第九课——线程通信_阻塞状态

线程第九课——线程通信_线程间通信_02 

线程第九课——线程通信_等待状态_03 


看到这里的人先暂停一下,把上面的截图过一遍。


下面来讲讲怎么用:

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);

}

}

}