三、线程间通信
1、wait方法、notify方法和notifyAll方法
- wait和notify为Object类的方法
- 在调用 wait() 之前,线程必须获得该对象的对象锁,即只有在同步方法或同步块中调用wait()方法,在执行wait()方法后,当前线程释放锁,如果没有持有适当的锁,则会抛出异常
- notify()方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程同时等待,则会随机调出一个呈wait状态的线程,对其发出通知notify(随机一个)
- notify()方法也必须只能在同步方法或者同步块中使用,执行完notify()方法后,当前线程不会马上释放对象锁,则必须等到执行notify()方法的线程将程序执行完,即退出synchronized代码块
- wait使线程停止运行,而notif使停止的线程继续运行、
- notifyAll使所有正在等待队列中等待同一共享资源的全部线程从等待状态中退出,优先级最高的线程最先执行,也可能是随机执行
- 当线程呈wait()状态,调用线程对象的interrupt()方法会出现InterruptedException异常
- wait(long)为等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒
举个例子说明:
public class MyThread1 extends Thread{ private Object lock; public MyThread1(Object lock) { super(); this.lock = lock; } @Override public void run() { try { synchronized (lock){ System.out.println("开始:" + Thread.currentThread().getName()); lock.wait(); System.out.println("结束:" + Thread.currentThread().getName()); } }catch (InterruptedException e){ e.printStackTrace(); } } } public class MyThread2 extends Thread{ private Object lock; public MyThread2(Object lock) { super(); this.lock = lock; } @Override public void run() { synchronized (lock){ System.out.println("开始:" + Thread.currentThread().getName()); lock.notify(); //notify结束后只有该方法执行完,其他线程才能获得对象锁 System.out.println("结束:" + Thread.currentThread().getName()); } } } public class Demo02Class { public static void main(String[] args) { try { Object object = new Object(); MyThread1 myThread1 = new MyThread1(object); myThread1.start(); Thread.sleep(2000); MyThread2 myThread2 = new MyThread2(object); myThread2.start(); }catch (InterruptedException e){ e.printStackTrace(); } } } 输出结果: 开始:Thread-0 开始:Thread-1 结束:Thread-1 结束:Thread-0
从以上输出结果可以看出notify结束后要该方法执行完才释放对象锁,其他线程才能获得对象锁
2、方法join的使用
- 作用是等待线程对象销毁
- 大部分主线程创建并启动子线程,如果子线程进行大量的耗时操作,主线程想等待子线程执行完成之后再结束,或者主线程要取得子线程处理的数据值,就要使用join方法