1.wait(),notify()与notifyAll():java
wait(),notify()与notifyAll方法是java.lang.Object类的方法,因此这些方法不能被子类重写,Object类是全部类的超类。
ide
void wait() | 致使线程进入等待状态,直到它被其余线程经过notify()或者notifyAll唤醒 |
void wait(long t) //毫秒 |
在其余线程调用此对象的 notify() 方法或notifyAll()方法,或者超过指定的时间量前,致使当前线程等待。 |
void wait(long t, int n) |
a. 其余线程经过调用
// wait(0) 与wait(0,0)相同this |
void notify() |
随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。 (单个线程) |
void notifyAll() | 唤醒在此对象监视器上等待的全部线程。spa |
wait(),notify(),notifyAll()必须写在同步方法中(synchronized方法内部或者synchronized块内部),这是由于这几个方法要求当前正在运行Object.wait()方法的线程拥有Object的对象锁,即当前线程必须拥有此对象监视器,不然将会抛出IllegalMonitorStateException(若是当前线程不是此对象监视器的全部者)
。即便你确实知道当前上下文线程确实拥有了对象锁,也不能将Object.wait()这样的语句写在当前上下文中。线程
wait():释放占有的对象锁,线程进入等待池,释放cpu,而其余正在等待的线程便可抢占此锁,得到锁的线程便可运行程序。而sleep()不一样的是,线程调用此方法后,会休眠一段时间,休眠期间,会暂时释放cpu,但并不释放对象锁。也就是说,在休眠期间,其余线程依然没法进入此代码内部。休眠结束,线程从新得到cpu,执行代码。wait()和sleep()最大的不一样在于wait()会释放对象锁,而sleep()不会!code
notify(): 该方法会唤醒由于调用对象的wait()而等待的线程,其实就是对对象锁的唤醒,从而使得wait()的线程能够有机会获取对象锁。调用notify()后,并不会当即释放锁,而是继续执行当前代码,直到synchronized中的代码所有执行完毕,才会释放对象锁。JVM则会在等待的线程中调度一个线程去得到对象锁,执行代码。须要注意的是,wait()和notify()必须在synchronized代码块中调用。notifyAll()则是唤醒全部等待的线程。orm
2.简单的生产者消费者例子:对象
//首先设定一个存放产品的缓冲区: public class CollectionBuffer { //缓冲区最大存储量 private final int MAX_SIZE = 100; //缓冲区存储量载体 LinkedList<Object> list = new LinkedList<Object>(); // 此实现并不是同步 public LinkedList<Object> getList() { return list; } public void setList(LinkedList<Object> list) { this.list = list; } public int getMAX_SIZE() { return MAX_SIZE; } //生产产品 num 个 public void produce( int num ){ //同步代码块 synchronized(list){ //若是仓库剩余量不足,即生产产品可能过多 while( list.size() + num > MAX_SIZE ){ System.out.println("即将生产产品数量为: " + num +" 但已有库存量为: "+ list.size() +" 暂时不能再进行生产任务<产品数量会大于最大库存量>"); try { //等会再生产,陷入等待状态(阻塞) 会释放对象锁,而sleep不会 list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //若是知足条件,则生产产品: for( int i=1;i<=num;i++){ list.add( new Object() ); } System.out.println("已经生产产品数量为:" + num + " 现生产后新的库存量为:" + list.size() ); list.notifyAll(); } } //消费产品 num 个 public void consume( int num ){ // 同步代码块 synchronized(list){ while( list.size() < num ){ System.out.println("想要消费产品数量为: " + num +" 但当前库存产品量为: " + list.size() +" 暂时还不能消费<库存量小于消费量>"); try { // 不知足消费条件,等待(阻塞) list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //若是知足消费条件, 即库存量足够消费者消费 消费量小于库存量。 for( int i=1;i<=num;i++){ list.remove(); } System.out.println("已经消费产品数量为: " + num + " 现消费后新的库存量为: " + list.size() ); list.notifyAll(); } } } // 生产者: public class Producer extends Thread { // 每次生产的产品量 private int num; //存放的仓库(缓冲容器) private CollectionBuffer collectionBuffer; // 构造函数 设置存储缓冲区仓库 public Producer(CollectionBuffer collectionBuffer){ this.collectionBuffer = collectionBuffer; } @Override public void run() { // 调用仓库缓冲区CollectionBuffer的生产函数 collectionBuffer.produce(num); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public CollectionBuffer getCollectionBuffer() { return collectionBuffer; } public void setCollectionBuffer(CollectionBuffer collectionBuffer) { this.collectionBuffer = collectionBuffer; } } //消费者: public class Consumer extends Thread{ //每次要消费的产品量: private int num; //消费产品的缓冲仓库区 private CollectionBuffer collectionBuffer; //构造函数 指定消费商品的缓冲区 public Consumer(CollectionBuffer collectionBuffer){ this.collectionBuffer = collectionBuffer; } @Override public void run() { //调用缓冲区中的消费产品的函数,指定消费量 collectionBuffer.consume(num); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public CollectionBuffer getCollectionBuffer() { return collectionBuffer; } public void setCollectionBuffer(CollectionBuffer collectionBuffer) { this.collectionBuffer = collectionBuffer; } } // 测试类: public class TestPC { public static void main(String[] args) throws InterruptedException { //建立仓库缓冲区对象 CollectionBuffer cb = new CollectionBuffer(); //建立多个生产者对象 Producer p1 = new Producer(cb); Producer p2 = new Producer(cb); Producer p3 = new Producer(cb); Producer p4 = new Producer(cb); Producer p5 = new Producer(cb); Producer p6 = new Producer(cb); //建立多个消费者对象 Consumer c1 = new Consumer(cb); Consumer c2 = new Consumer(cb); Consumer c3 = new Consumer(cb); Consumer c4 = new Consumer(cb); Consumer c5 = new Consumer(cb); Consumer c6 = new Consumer(cb); //开始设置生产者生产产品数量 p1.setNum(10); p2.setNum(20); p3.setNum(30); p4.setNum(60); p5.setNum(80); p6.setNum(90); //开始让消费者消费产品数量 c1.setNum( 80 ); c2.setNum( 60 ); c3.setNum( 50 ); c4.setNum( 35 ); c5.setNum( 20 ); c6.setNum( 10 ); // 让线程开始执行 c1.start(); c2.start(); p1.start(); p2.start(); c6.start(); p4.start(); c3.start(); p3.start(); p5.start(); c4.start(); p6.start(); c5.start(); } }