使用wait/notify来实现生产者消费者时能够达到在线程阻塞的效果,这样就不会出现轮询,然后浪费cpu时间的目的。代码如下:
1. 状态类,表示是否已经生产:
1 package com.demo; 2 3 public class State { 4 5 public State() { 6 flag = false; 7 } 8 9 public boolean flag; 10 }
2. 生产者类:
1 package com.demo; 2 3 public class Productor extends Thread { 4 5 public com.demo.State state; 6 7 @Override 8 public void run() { 9 for(int i=0; i<10;) { 10 try { 11 synchronized(state) { 12 if(state.flag) { 13 state.wait(); 14 } else { 15 System.out.println("product: " + i); 16 i++; 17 state.flag = true; 18 state.notify(); 19 } 20 } 21 } 22 catch(Exception ex) { 23 24 } 25 } 26 } 27 }
3. 消费者类:
1 package com.demo; 2 3 public class Consumer extends Thread { 4 5 public com.demo.State state; 6 7 public void run(){ 8 for(int i=0; i<10;) { 9 try { 10 synchronized(state) { 11 if(!state.flag) { 12 state.wait(); 13 } else { 14 System.out.println("consumer: " + i); 15 i++; 16 state.flag = false; 17 state.notify(); 18 } 19 } 20 } 21 catch(Exception ex) { 22 23 } 24 } 25 } 26 }
4. 测试类
1 package com.demo; 2 3 public class Program { 4 5 public static void main(String[] args) throws Exception { 6 State state = new State(); 7 Productor productor = new Productor(); 8 productor.state = state; 9 Consumer consumer = new Consumer(); 10 consumer.state = state; 11 Thread th1 = new Thread(productor); 12 Thread th2 = new Thread(consumer); 13 th1.start(); 14 th2.start(); 15 th1.join(); 16 th2.join(); 17 } 18 }
在生产者和消费者每次执行的时候总是先判断state.flag的状态,为false表示已经没有生产,这样消费者应该等待,而生产者应该生产;为true表示已经生产,这样生产者应该等待,而消费者应该消费。而这生产者生产了后将flag设置为true,这样就表示已经生产了,然后通知消费者,这样生产者再次执行的时候发现消费者还没消费的话就处于阻塞状态,而消费者在收到通知后就开始消费过程,然后将flag设置为false,再通知生产者,如此周而复始。
使用wait/notify可能会应为线程的执行的先后顺序不同而造成死锁,而在本实现中是通过同一个对象的flag属性的真假来判断的,所以即便执行顺序不一致,也不会出现消费者先于生产者生产前消费,所以也就避免了死锁。