3、传统线程同步与通信--生产消费例子
核心点:
1、锁对象必须是同一个。
2、wait()和notify()方法必须是调用锁对象的方法,而非this(线程)的。
3、在多生产多消费的时候注意使用notifyAll而不是notifyAll,否则会造成死锁
4、将需要同步的多个方法尽量分布在同一个对象里。
测试代码:
1 import java.util.LinkedList; 2 import java.util.Queue; 3 import java.util.Random; 4 5 /** 6 * 多个生产 - 消费 线程同步通信 7 * 核心点: 8 * 1、锁对象必须是同一个。 9 * 2、wait()和notify()方法必须是调用锁对象的方法,而非this(线程)的。 10 * 3、在多生产多消费的时候注意使用notifyAll而不是notifyAll 11 * @author yzl 12 * 13 */ 14 public class ThreadPart_3 { 15 public static void main(String[] args) { 16 test(); 17 } 18 public static void test(){ 19 final Factory factory = new Factory(); 20 Thread shengchan1 = new Thread(new Runnable() { 21 @Override 22 public void run() { 23 while(true){ 24 factory.add(); 25 } 26 } 27 }); 28 shengchan1.start(); 29 Thread shengchan2 = new Thread(new Runnable() { 30 @Override 31 public void run() { 32 while(true){ 33 factory.add(); 34 } 35 } 36 }); 37 shengchan2.start(); 38 39 Thread xiaofei1 = new Thread(new Runnable() { 40 @Override 41 public void run() { 42 while(true){ 43 factory.sub(); 44 45 } 46 } 47 }); 48 xiaofei1.start(); 49 Thread xiaofei2 = new Thread(new Runnable() { 50 @Override 51 public void run() { 52 while(true){ 53 factory.sub(); 54 } 55 } 56 }); 57 xiaofei2.start(); 58 } 59 } 60 61 class Factory{ 62 private Queue<Integer> queue = new LinkedList<Integer>(); 63 //生产 64 public synchronized void add(){ 65 //用while代替if来防止假唤醒 66 while(queue.size() > 0){ 67 try { 68 this.wait(); 69 } catch (InterruptedException e) { 70 e.printStackTrace(); 71 } 72 } 73 Integer val = new Random().nextInt(100); 74 queue.add(val); 75 System.out.println("生产者:" + Thread.currentThread().getName()+" add :" + val); 76 this.notifyAll(); 77 try { 78 Thread.sleep(1000); 79 } catch (InterruptedException e) { 80 e.printStackTrace(); 81 } 82 } 83 //消费 84 public synchronized void sub(){ 85 //用while代替if来防止假唤醒 86 while(queue.size() == 0 ){ 87 try { 88 this.wait(); 89 } catch (InterruptedException e) { 90 e.printStackTrace(); 91 } 92 } 93 Integer val = queue.poll(); 94 System.out.println("消费者:" + Thread.currentThread().getName()+" get : " + val); 95 this.notifyAll(); 96 try { 97 Thread.sleep(1000); 98 } catch (InterruptedException e) { 99 e.printStackTrace(); 100 } 101 } 102 }
运行结果示例:
1 生产者:Thread-0 add :12 2 消费者:Thread-3 get : 12 3 生产者:Thread-1 add :84 4 消费者:Thread-2 get : 84 5 生产者:Thread-0 add :28 6 消费者:Thread-3 get : 28 7 生产者:Thread-1 add :60 8 消费者:Thread-2 get : 60 9 生产者:Thread-0 add :71 10 消费者:Thread-3 get : 71 11 生产者:Thread-1 add :63 12 消费者:Thread-3 get : 63 13 生产者:Thread-0 add :3 14 消费者:Thread-2 get : 3 15 生产者:Thread-1 add :62 16 消费者:Thread-3 get : 62 17 生产者:Thread-0 add :90 18 消费者:Thread-2 get : 90 19 生产者:Thread-1 add :9 20 消费者:Thread-3 get : 9