这节课我们来填坑,讲讲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); } } }