• java学习之多生产者和多消费者


    在上一节当中我们说道了,java多线程当中单个消费者对应单个生产者的关系。这个时候有几个点需要注意一下,第一个就是把if判断flag的语句改成while这样能够避免,比如如果我们这个时候用if的话判断完为真之后,线程就睡过去了,但是当下一次线程notify的时候,这个时候生产者还有消费者,也就是一个锁上面的线程拥有线程苏醒的机会是等同的。这个时候,如果生产者冻结之后,紧接着notify的话这个时候苏醒的还可能是生产者,这是我们不愿意看到的。那我们应该如何来处理呢,这个时候我们就应该把if改成while因为while是个循环,当下一次该线程苏醒的时候还应到回过头来判断,flag标记,这样就避免了生产者自我唤醒的这种情况。

    但是现在问题变了,就是这个时候有多个生产者还有多个消费者,我们知道当只有一个生产者还有一个消费者的时候,至少会唤醒其中的一个,那么要是多个生产者还有多个消费者呢,我们可以这样想一下,比如说这个时候有两个生产者A和B,还有两个消费者C和D,此时A生产完了之后,这个时候A就开始唤醒了,假如A唤醒了C这个时候C开始生产消费产品,消费完了之后开始通知其他线程,这个时候假如被唤醒的是D线程,因为flag是假的证明已经没有东西可消费了,这个时候他又冻结。那么这个时候其他线程就都被冻结了,这个时候就形成了死锁现象,如果要避免死锁现象的话,java又为我们提供了一个方法,叫做notifyAll()方法,这个方法的作用在于能够把所有的线程都唤醒,这样就能保证消费者还有生产者至少可以唤醒双方的一个线程,保证程序的正常运行。这样做的一个缺点就是其中还有一个属于己方的线程被唤醒,这样就浪费了资源。于是在jdk更新的时候,就为我们提供了一个新的api能够显式的来操作锁还有唤醒冻结线程,这个线程不再核心lang包当中,这个apijava.util.concurrent.locks这个包当中为我们提供了两个接口,一是Lock接口还有一个是Condition接口。Lock接口扩展的方法有lock()方法还有一个unlock方法,这里需要注意的一点是,无论如何一定要释放锁,这个时候就用到了前面异常所讲到的finally语句,无论如何一定要执行。Lock当中还扩展了一个方法就是newCondition()这个方法,这个方法的作用是给一个锁定义多个消息传递的方式也就是给线程绑定多个监视器,比如说生产者只唤醒消费者的线程,而不唤醒生产者的线程,同理消费者也是如此。同时在Lock当中等待的方法不是wait()方法,唤醒的方法也不是notify()方法,这两个方法分别对应Lock当中的await()方法和signal()方法。

    我们综合上面所讲来用代码体现下:

      1 import java.util.concurrent.locks.*;
      2 class KaoYa
      3 {
      4 
      5     int num = 1;
      6 
      7     Lock l = new ReentrantLock();
      8 
      9     Condition c1 = l.newCondition(); 
     10     Condition c2 = l.newCondition(); 
     11 
     12     boolean flag;
     13 
     14     public void produce() throws InterruptedException
     15     {
     16             l.lock();
     17             
     18             try{
     19                 while(true)
     20                 {
     21                     while(flag)
     22                         c1.await();
     23                         System.out.println(Thread.currentThread().getName()+"KaoYa...."+num);
     24                         flag = true;
     25                         c2.signal();
     26                 }        //num++;
     27         
     28             }finally
     29             {
     30                 l.unlock();
     31             }
     32     }
     33 
     34     public void consume() throws InterruptedException
     35     {
     36         l.lock();
     37             
     38             try{
     39                 while(true)
     40                 {
     41                     while(!flag)
     42                         c2.await();
     43                     System.out.println(Thread.currentThread().getName()+"KaoYa------"+num);
     44                     num++;
     45                     flag = false;
     46                     c1.signal();    
     47                 }                
     48             }finally
     49             {
     50 
     51                 l.unlock();
     52 
     53             }
     54     }
     55 
     56 }
     57 
     58 class Product implements Runnable
     59 {
     60 
     61     KaoYa k;
     62     Product(KaoYa k)
     63     {
     64 
     65         this.k = k;
     66 
     67     }
     68 
     69     public void run()
     70     {
     71         try{
     72             k.produce();
     73         }catch(InterruptedException e)
     74         {
     75 
     76         }
     77     }
     78 }
     79 
     80 
     81 class Consume implements Runnable
     82 {
     83 
     84     KaoYa k;
     85     Consume(KaoYa k)
     86     {
     87 
     88         this.k = k;
     89 
     90     }
     91 
     92     public void run()
     93     {
     94     
     95         try{
     96             k.consume();
     97         }catch(InterruptedException e)
     98         {
     99 
    100         }
    101             
    102 
    103     }
    104 
    105 
    106 }
    107 
    108 class LockDemo
    109 {
    110 
    111     public static void main(String[] args) {
    112         
    113         KaoYa k = new KaoYa();
    114         Product p = new Product(k);
    115         Consume c = new Consume(k);
    116 
    117         Thread t1 = new Thread(p);
    118         Thread t2 = new Thread(p);
    119         Thread t3 = new Thread(c);
    120         Thread t4 = new Thread(c);
    121 
    122 
    123         t1.start();
    124         t2.start();
    125         t3.start();
    126         t4.start();
    127 
    128     }
    129 
    130 }

  • 相关阅读:
    Windows Internals学习笔记(八)IO系统
    FPGA相关术语(一)
    Bilinear Filter
    总线与接口
    GPIO相关知识
    .NET IL学习笔记(一)
    Windows Internals学习笔记(七)Image Loader
    Windows Internals学习笔记(五)Synchronization
    struts2官方 中文教程 系列五:处理表单
    struts2官方 中文教程 系列四:Action
  • 原文地址:https://www.cnblogs.com/sunchuanzhen/p/3381459.html
Copyright © 2020-2023  润新知