Java并发系列(五)线程间的通信


分类: Java   52人阅读  评论(0)  收藏  举报

目录(?)[+]

Author:Martin

E-mail:mwdnjupt@sina.com.cn

CSDN Blog:http://blog.csdn.net/ictcamera

Sina MicroBlog ID:ITCamera

Main Reference:

《Java并发编程实战》 Brian Goetz etc 童云兰等译

《Java并发设计教程》 温绍锦

线程间的通信的最典型例子就是“生产者-消费者”问题。下面用不同的方式来实现该问题。生产者消费者模型:(很简单)若干个生产者线程向缓存中存放对象,而若干消费者线程从缓存中获取(移除)对象,这个过程要保证操作的一致性。

1.        wait-nofity实现

线程的wait-nofity方法是Java线程之间基础的交互工具,利用它可以实现 “生产者-消费者问题”,线程的生命周期如下图所示:

 

线程生命周期图:引用图片链接 http://www.haogongju.net/art/1835120

代码如下所示:

[java]  view plain copy
  1. //货物类  
  2. public class Item {  
  3.     private static long count=0;  
  4.     private long id=0;  
  5.     private String name;  
  6.     public Item(String name){  
  7.         this.id=++count;  
  8.         this.name=name;  
  9.     }  
  10.     public String getName() {  
  11.         return name;  
  12.     }  
  13.     public void setName(String name) {  
  14.         this.name = name;  
  15.     }  
  16.     public long getId() {  
  17.         return id;  
  18.     }  
  19.     public String toString(){  
  20.         return "id="+id;  
  21.     }  
  22. }  
  23. //仓库类  
  24. public class Warehouse {  
  25.     private final int MAX_LENGTH=10;  
  26.     private Stack<Item> stack=new Stack<Item>();  
  27.     private boolean isFull=false;  
  28.     private boolean isEmpty=true;  
  29.     public synchronized void produce(Item item){  
  30.         if(isFull){  
  31.             try {  
  32.                 this.wait();  
  33.             } catch (InterruptedException e) {  
  34.                 e.printStackTrace();  
  35.             }  
  36.         }else{  
  37.             // 为了更清楚的看打印结果,让线程执行慢点,sleep一段时间  
  38.             try {  
  39.                 Thread.sleep(10);  
  40.             } catch (InterruptedException e) {  
  41.                 Thread.currentThread().interrupt();  
  42.                 e.printStackTrace();  
  43.             }  
  44.             stack.push(item);  
  45.             System.out.println("Procucer:"+Thread.currentThread().getName()  
  46.                             +" procduced:"+item+", current Warehouse="+stack);  
  47.             isFull=stack.size()==MAX_LENGTH;  
  48.             isEmpty=stack.isEmpty();  
  49.             this.notifyAll();  
  50.         }  
  51.           
  52.     }  
  53.     public synchronized void cosume(){  
  54.         if(isEmpty){  
  55.             try {  
  56.                 this.wait();  
  57.             } catch (InterruptedException e) {  
  58.                 e.printStackTrace();  
  59.             }  
  60.         }else{  
  61.             // 为了更清楚的看打印结果,让线程执行慢点,sleep一段时间  
  62.             try {  
  63.                 Thread.sleep(10);  
  64.             } catch (InterruptedException e) {  
  65.                 Thread.currentThread().interrupt();  
  66.                 e.printStackTrace();  
  67.             }  
  68.             Item item=stack.pop();  
  69.             System.out.println("Consumer:"+Thread.currentThread().getName()  
  70.                             +" comsumeed:"+item+", current Warehouse="+stack);  
  71.             isFull=stack.size()==MAX_LENGTH;  
  72.             isEmpty=stack.isEmpty();  
  73.             this.notifyAll();  
  74.         }  
  75.     }  
  76. }  
  77. //生产者类  
  78. public class Productor implements Runnable{  
  79.     private String name;  
  80.     private Warehouse warehouse=new Warehouse();  
  81.     public Productor (String name,Warehouse warehouse){  
  82.         this.name=name;  
  83.         this.warehouse=warehouse;  
  84.     }  
  85.     public void run() {  
  86.         while (true){  
  87.             Item item=new Item(name);  
  88.             warehouse.produce(item);  
  89.         }  
  90.     }  
  91. }  
  92. //消费者类  
  93. public class Consumer implements Runnable{  
  94.     private String name;  
  95.     private Warehouse warehouse=new Warehouse();  
  96.     public Consumer (String name,Warehouse warehouse){  
  97.         this.name=name;  
  98.         this.warehouse=warehouse;  
  99.     }  
  100.     public void run() {  
  101.         while (true){  
  102.             warehouse.cosume();  
  103.         }  
  104.     }  
  105. }  
  106. //测试类  
  107. public class Test {  
  108.     public static void main(String[] args) {  
  109.         Warehouse warehouse=new Warehouse();  
  110.         Thread productor1= new Thread(new Productor("productor1",warehouse),"productor1");  
  111.         Thread productor2= new Thread(new Productor("productor2",warehouse),"productor2");  
  112.         Thread consumer1= new Thread(new Consumer("consumer1",warehouse),"consumer1");  
  113.         Thread consumer2= new Thread(new Consumer("consumer2",warehouse),"consumer2");  
  114.         Thread consumer3= new Thread(new Consumer("consumer3",warehouse),"consumer3");  
  115.         Thread consumer4= new Thread(new Consumer("consumer4",warehouse),"consumer4");  
  116.         Thread consumer5= new Thread(new Consumer("consumer5",warehouse),"consumer5");  
  117.         Thread consumer6= new Thread(new Consumer("consumer6",warehouse),"consumer6");  
  118.         productor1.start();  
  119.         productor2.start();  
  120.         consumer1.start();  
  121.         consumer2.start();  
  122.         consumer3.start();  
  123.         consumer4.start();  
  124.         consumer5.start();  
  125.         consumer6.start();    
  126.     }  
  127. }  

2.        显式锁Lock实现

上面的“生产者-消费者”模型也可以用显式锁Lock实现。代码如下:

[java]  view plain copy
  1. //仓库类  
  2. public class BlockQueue<T>{  
  3.     private static final int MAX_LEN = 5;//假设队列长度为5  
  4.     private List<T> blockQueue=null;//使用List模拟队列  
  5.     private ReentrantLock    lock    = new ReentrantLock();  
  6.     private Condition        produce = lock.newCondition();  
  7.     private Condition        consume = lock.newCondition();  
  8.     public BlockQueue(List<T> queue){  
  9.         blockQueue = queue;  
  10.     }  
  11.     public BlockQueue(){  
  12.           
  13.     }  
  14.     public void put(T t) throws InterruptedException{  
  15.         try{  
  16.             lock.lock();// 防止两个生产者线程同时进入  
  17.             if(isFull())  
  18.             {  
  19.                 produce.await();// 生产者等待  
  20.             }  
  21.             System.out.println(Thread.currentThread().getName()   
  22.                             + "生产者生产了一个数据:" + t);  
  23.             blockQueue.add(t);  
  24.             simulateTimeSpend();  
  25.             consume.signalAll();// 通知所有的消费者我生产了元素  
  26.         }finally{  
  27.             lock.unlock();  
  28.         }  
  29.     }  
  30.     public T take() throws InterruptedException{  
  31.         T element = null;  
  32.         try{  
  33.             lock.lock();// 防止两个消费者线程同时进入  
  34.             if(isEmpty())  
  35.             {  
  36.                 consume.await();// 消费这等待  
  37.             }  
  38.             simulateTimeSpend();  
  39.             element = getFirstElement();  
  40.             System.out.println(Thread.currentThread().getName()   
  41.                             + " 消费者取得数据:" + getValue(element));  
  42.             produce.signalAll();// 通知  
  43.             return element;  
  44.         }finally{  
  45.             lock.unlock();  
  46.         }  
  47.     }  
  48.     private T getFirstElement(){    
  49.        // 取队头元素  
  50.        if(!blockQueue.isEmpty()){  
  51.            T result=blockQueue.get(0);  
  52.            blockQueue.remove(result);  
  53.            return result;  
  54.        }  
  55.        return null;   
  56.     }  
  57.     public boolean isEmpty(){  
  58.         return blockQueue.isEmpty();  
  59.     }  
  60.     public boolean isFull(){  
  61.         return blockQueue.size()== MAX_LEN;  
  62.     }  
  63.     /** 
  64.      * 模拟生产或者消费要花费一段时间 2013-3-8下午02:35:46 
  65.      * 推荐随机休眠一段时间 
  66.      */  
  67.     private void simulateTimeSpend()  
  68.     {  
  69.         try{  
  70.             Thread.sleep(1000);  
  71.         }catch(InterruptedException e){  
  72.               
  73.             e.printStackTrace();  
  74.         }  
  75.     }  
  76.     public String getValue(T t){  
  77.         if(t instanceof Integer){  
  78.             Integer result=(Integer)t;  
  79.             return String.valueOf(result.intValue());  
  80.         }  
  81.         return t.toString();  
  82.     }  
  83. }  
  84. //生产者类  
  85. public class Productor implements Runnable{  
  86.     BlockQueue<Integer> queue ;  
  87.     public Productor(BlockQueue<Integer> queue){  
  88.         this.queue = queue;  
  89.     }  
  90.     @Override  
  91.     public void run()  
  92.     {  
  93.         while(true)  
  94.         {  
  95.             int data = new Random().nextInt(100000);//产生一个随机数放入  
  96.             waitMonenet();//随机等待一段时间  
  97.             try{  
  98.                 queue.put(data);  
  99.             }catch(InterruptedException e){    
  100.                 e.printStackTrace();  
  101.             }  
  102.         }  
  103.   
  104.     }  
  105.     private void waitMonenet()  
  106.     {  
  107.         try{  
  108.             Thread.sleep(new Random().nextInt(1000));  
  109.         }catch(InterruptedException e){  
  110.             e.printStackTrace();  
  111.         }  
  112.     }  
  113. }  
  114. //消费者类  
  115. public class Consumer implements Runnable{  
  116.     BlockQueue<Integer> queue ;  
  117.     public Consumer(BlockQueue<Integer> queue){  
  118.         this.queue = queue;  
  119.     }  
  120.     @Override  
  121.     public void run()  
  122.     {  
  123.         while(true)  
  124.         {  
  125.             waitMonenet();  
  126.             try{  
  127.                 queue.take();  
  128.             }catch(InterruptedException e){  
  129.                 e.printStackTrace();  
  130.             }  
  131.         }  
  132.   
  133.     }  
  134.     private void waitMonenet()  
  135.     {  
  136.         try{  
  137.             Thread.sleep(new Random().nextInt(1000));  
  138.         }catch(InterruptedException e){  
  139.   
  140.             e.printStackTrace();  
  141.         }  
  142.     }  
  143. }  
  144. //测试类  
  145. public class Test  
  146. {  
  147.     public static void main(String[] args)  
  148.     {  
  149.         List<Integer> data = new ArrayList<Integer>();  
  150.         BlockQueue<Integer> queue = new BlockQueue<Integer>(data);  
  151.         Thread producerA=new Thread(new Productor(queue));  
  152.         producerA.setName("Producer_A");  
  153.         Thread producerB=new Thread(new Productor(queue));  
  154.         producerB.setName("Producer_B");  
  155.         Thread consumerA=new Thread(new Consumer(queue));  
  156.         consumerA.setName("Consumer_A");  
  157.         producerA.start();  
  158.         producerB.start();  
  159.         consumerA.start();  
  160.     }  
  161. }  


3.        并发容器实现

上面的“生产者-消费者”模型也很容易用并发容器-阻塞队列实现。代码如下:

[java]  view plain copy
  1. //货物类  
  2. public class Item  
  3. {  
  4.     //产品序列号  
  5.     private long id;  
  6.     public Item(long id1)  
  7.     {  
  8.         id = id1;  
  9.     }  
  10.     public long getId()  
  11.     {  
  12.         return id;  
  13.     }  
  14. }  
  15. //仓库类  
  16. public class Warehouse{  
  17.     //定长阻塞队列  
  18.     private ArrayBlockingQueue<Item> queue;  
  19.     //通过构造函数传入仓库容量  
  20.     public Warehouse(int capacity){  
  21.         queue = new ArrayBlockingQueue<Item>(capacity);  
  22.     }  
  23.     //向仓库里添加产品,如果仓库已满,等待。。。  
  24.     public void put(Item pro){  
  25.         try{  
  26.             queue.put(pro);  
  27.         }catch(InterruptedException e){  
  28.             e.printStackTrace();  
  29.         }  
  30.     }  
  31.     //从仓库取产品,如果仓库为空,等待。。。  
  32.     public Item take(){  
  33.         try{  
  34.             return queue.take();  
  35.         }catch(InterruptedException e){  
  36.             e.printStackTrace();  
  37.         }  
  38.         return null;  
  39.     }  
  40. }  
  41. //生产者类  
  42. public class Productor implements Runnable{  
  43.     //产品序列号生成器  
  44.     private static AtomicLong idManager = new AtomicLong();  
  45.     //仓库  
  46.     private Warehouse wareHouse;  
  47.     //通过构造函数传入仓库  
  48.     public Productor(Warehouse wareHouse1){  
  49.         wareHouse = wareHouse1;  
  50.     }  
  51.     @Override  
  52.     public void run()  
  53.     {  
  54.         while(true)  
  55.         {  
  56.             //生产一件产品,序列号用 序列号生成器  
  57.             Item pro = new Item(idManager.getAndIncrement());  
  58.             //添加到仓库中  
  59.             wareHouse.put(pro);  
  60.             System.out.println("生产:"+pro.getId());  
  61.         }  
  62.     }  
  63. }  
  64. //消费者类  
  65. public class Consumer implements Runnable  
  66. {  
  67.     //仓库  
  68.     private Warehouse wareHouse;  
  69.     //通过构造函数传入仓库  
  70.     public Consumer(Warehouse wareHouse1)  
  71.     {  
  72.         wareHouse = wareHouse1;  
  73.     }  
  74.     @Override  
  75.     public void run()  
  76.     {  
  77.         while(true)  
  78.         {  
  79.             //从仓库取产品  
  80.             Item pro = wareHouse.take();  
  81.             System.out.println("消费:"+pro.getId());  
  82.         }  
  83.     }  
  84. }  
  85. //测试类  
  86. public class Test  
  87. {  
  88.     public static void main(String[] args)  
  89.     {  
  90.         //50个线程  
  91.         ExecutorService pool = Executors.newFixedThreadPool(50);  
  92.         //仓库容量1000  
  93.         Warehouse warehouse = new Warehouse(1000);  
  94.         //10个生产者  
  95.         for(int i = 1 ; i <= 10 ;i  ++)  
  96.         {  
  97.             pool.execute(new Productor(warehouse));  
  98.         }  
  99.         //40个消费者  
  100.         for(int i = 1 ; i <= 40 ;i  ++)  
  101.         {  
  102.             pool.execute(new Consumer(warehouse));  
  103.         }  
  104.     }  
  105. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值