05_线程间通信
【简述】
为了支持多线程之间的协作,JDK提供了两个重要的线程方法:通知notify()、等待wait()。
任何对象都可以调用这两个方法,因为他们在Object类中。
【wait方法】
当一个对象调用了wait方法之后,当前线程就会在这个对象上等待。比如,线程A中,调用了obj.wait()方法,那么线程A就会停止执行,而转为等待状态,同时当前线程释放持有的锁,线程A会一直等待到其它线程调用了obj.notify()方法通知到自己位置。obj对象成为了多个线程之间通信的手段。
【wait方法和notify方法工作细节】
如果一个线程调用了object.wait(),那么他就会进入object对象的等待队列。这个等待队列中,可能会有多个线程,因为系统运行多个线程同时会等待某一对象,当object.notify()方法被调用后,它就会从这个等待队列中随机选择一个线程(和队列中的顺序无关),并将其唤醒。
notifyAll()可以唤醒所有的等待线程,而不是随机选择一个。
注意:object.wait()方法不可以随意调用,必须包含在对应的synchronizd语句中。无论是wait()还是notify()方法都需要获得目标对象的一个监听器。
【使用wait和notify的注意点】
1.wait和notify必须配合synchronized关键字使用
2.wait方法释放锁,而notify不会释放锁
【例子】
package com.part1.sync005; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleWN { final static Object object = new Object(); public static class T1 extends Thread{ @Override public void run() { synchronized(object){ System.out.println(getNowTime()+" T1 start!!!"); try{ Thread.sleep(1000); System.out.println(getNowTime()+" T1 wait for Object... "); object.wait(); //T1释放锁,等待其他线程来唤醒 }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(getNowTime()+" T1 end..."); } } } public static class T2 extends Thread{ @Override public void run() { synchronized(object){ try { System.out.println(getNowTime()+" T2 start !!! notify one Thread !!!"); object.notify(); //从object等待队列中随机唤醒一个等待线程,此时只有T1在等待,故唤醒T1 System.out.println(getNowTime()+" T2 end..."); //虽然T2唤醒了T1线程,但是T2此时依然持有锁,所以T1处于阻塞状态 Thread.sleep(2000); //T2执行结束,释放锁,T1方可去获取锁 } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Thread t1 = new T1(); Thread t2 = new T2(); t1.start(); t2.start(); } public static String getNowTime(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(new Date()); } }
【运行结果】