zoukankan      html  css  js  c++  java
  • 线程间的通信_多生产者多消费者问题_JDK1.5新特性_Lock

    对于同步代码块,对于锁的操作是隐式的
    但是在JDK1.5之前的这种方法效率有点低,判断会很多,后面升级之后有新的解决方案

    jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作

    Lock接口:替代了同步代码块或者同步函数,将同步的隐式锁操作变成显示锁操作,同时更为灵活,可以一个锁上加上多组监视器

         lock():获取锁       unlock():释放锁,通常定义在finally代码块中

    Condition接口:替代了Object中的wait notify notifyAll方法,将这些监视器方法单独封装,变成了Condition监视器对象,可以喝任意锁组合

            await();    singal();       singalAll();

    同步代码块到lock的变化:

     

     1 import java.util.concurrent.locks.*;//lock在此包中
     2 class LockDemo{
     3     public static void main(String[] args) {
     4         Resrouce r = new Resrouce();
     5         Producer pro = new Producer(r);
     6         Consumer con = new Consumer(r);
     7 
     8         Thread t1 = new Thread(pro);
     9         Thread t2 = new Thread(pro);
    10         Thread t3 = new Thread(con);
    11         Thread t4 = new Thread(con);
    12 
    13         t1.start();
    14         t2.start();
    15         t3.start();
    16         t4.start();
    17 
    18     }
    19 }
    20 
    21 class Resrouce{
    22     private String name;
    23     private int count = 1;
    24     private boolean flag = false;
    25 
    26     Lock lock = new ReentrantLock();//创建一个锁对象
    27     
    28     public void set(String name){
    29         lock.lock();
    30         try{
    31             while(flag)
    32                 try{this.wait();}catch(Exception e){}
    33             this.name = name+count;
    34             count++;
    35             System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
    36             flag = true;
    37             notifyAll();
    38         }finally{
    39             lock.unlock();
    40         }
    41         
    42     }
    43 
    44     public void out(){
    45         lock.lock();
    46         try{
    47             while(!flag)
    48                 try{this.wait();}catch(Exception e){}
    49             System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);
    50             flag = true;
    51             notifyAll();
    52         }finally{
    53             lock.unlock();
    54         }
    55     }
    56 }
    57 
    58 
    59 class Producer implements Runnable{
    60     private Resource r;
    61     Producer(Resource r){
    62         this.r = r; 
    63     }
    64     public void run(){
    65         while(true){
    66             r.set("烤鸭");
    67         }
    68     }
    69 }
    70 
    71 
    72 class Consumer implements Runnable{
    73     private Resource r;
    74     Consumer(Resource r){
    75         this.r = r; 
    76     }
    77     public void run(){
    78         while(true){
    79             r.out();
    80         }
    81     }
    82 }

     上述实例中锁换成了lock之后就不能用this来操作wait等方法了,应该用lock锁中的Condition接口中的方法,该接口将Object监视器方法(wait,notify,notifyAll)分解成不同的对象

     1 import java.util.concurrent.locks.*;
     2 class LockDemo{
     3     public static void main(String[] args) {
     4         Resrouce r = new Resrouce();
     5         Producer pro = new Producer(r);
     6         Consumer con = new Consumer(r);
     7 
     8         Thread t1 = new Thread(pro);
     9         Thread t2 = new Thread(pro);
    10         Thread t3 = new Thread(con);
    11         Thread t4 = new Thread(con);
    12 
    13         t1.start();
    14         t2.start();
    15         t3.start();
    16         t4.start();
    17 
    18     }
    19 }
    20 
    21 class Resrouce{
    22     private String name;
    23     private int count = 1;
    24     private boolean flag = false;
    25     
    26     Lock lock = new ReentrantLock();
    27     
    28     //通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器
    29     Condition con = lock.newCondition();
    30 
    31     public void set(String name){
    32         lock.lock();
    33         try{
    34             while(flag)
    35                 try{con.await();}catch(Exception e){}
    36             this.name = name+count;
    37             count++;
    38             System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
    39             flag = true;
    40             con.signalAll();
    41         
    42         }finally{
    43             lock.unlock();
    44         }
    45     }
    46 
    47     public void out(){
    48         lock.lock();
    49         try{
    50             while(!flag)
    51                 try{con.await();}catch(Exception e){}
    52             System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);
    53 
    54             flag = true;
    55             con.signalAll();
    56         }finally{
    57             lock.unlock();
    58         }
    59     }
    60 }
    61 
    62 
    63 class Producer implements Runnable{
    64     private Resource r;
    65     Producer(Resource r){
    66         this.r = r; 
    67     }
    68     public void run(){
    69         while(true){
    70             r.set("烤鸭");
    71         }
    72     }
    73 }
    74 
    75 
    76 class Consumer implements Runnable{
    77     private Resource r;
    78     Consumer(Resource r){
    79         this.r = r; 
    80     }
    81     public void run(){
    82         while(true){
    83             r.out();
    84         }
    85     }
    86 }

     上述实例只有一组监视器,既监视着生产者,又监视着消费者,可以搞两个监视器,一组监视生产者,一组监视消费者

     1 import java.util.concurrent.locks.*;
     2 class LockDemo{
     3     public static void main(String[] args) {
     4         Resrouce r = new Resrouce();
     5         Producer pro = new Producer(r);
     6         Consumer con = new Consumer(r);
     7 
     8         Thread t1 = new Thread(pro);
     9         Thread t2 = new Thread(pro);
    10         Thread t3 = new Thread(con);
    11         Thread t4 = new Thread(con);
    12 
    13         t1.start();
    14         t2.start();
    15         t3.start();
    16         t4.start();
    17 
    18     }
    19 }
    20 
    21 class Resrouce{
    22     private String name;
    23     private int count = 1;
    24     private boolean flag = false;
    25     
    26     Lock lock = new ReentrantLock();
    27     
    28     /*
    29         通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器
    30         Condition con = lock.newCondition();
    31     */
    32 
    33     //通过已有的锁获取监视器对象(两组),一组监视生产者,一组监视消费者
    34     Condition Producer_con = lock.newCondition();
    35     Condition Consumer_con = lock.newCondition();
    36     public void set(String name){
    37         lock.lock();
    38         try{
    39             while(flag)
    40                 try{Producer_con.await();}catch(Exception e){}
    41             this.name = name+count;
    42             count++;
    43             System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
    44             flag = true;
    45             //con.signalAll();//会发生死锁,所以要用到notifyAll
    46             Consumer_con.signa();//有了两组监视器后就不用signaAll方法唤醒所有线程池中的线程了,只唤醒对方的一个线程,这样效率就高很多了
    47         }finally{
    48             lock.unlock();
    49         }
    50     }
    51 
    52     public void out(){
    53         lock.lock();
    54         try{
    55             while(!flag)
    56                 try{Consumer_con.await();}catch(Exception e){}
    57             System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);
    58 
    59             flag = true;
    60             //con.signalAll();
    61 
    62             Producer_con.signal();
    63         }finally{
    64             lock.unlock();
    65         }
    66     }
    67 }
    68 
    69 
    70 class Producer implements Runnable{
    71     private Resource r;
    72     Producer(Resource r){
    73         this.r = r; 
    74     }
    75     public void run(){
    76         while(true){
    77             r.set("烤鸭");
    78         }
    79     }
    80 }
    81 
    82 
    83 class Consumer implements Runnable{
    84     private Resource r;
    85     Consumer(Resource r){
    86         this.r = r; 
    87     }
    88     public void run(){
    89         while(true){
    90             r.out();
    91         }
    92     }
    93 }

    wait和sleep的区别:

    wait和sleep都是让线程处于冻结状态的方法
    区别:
      1.wait可以指定时间也可以不指定。sleep必须指定时间。
      2.在同步中时,对CPU的执行权和锁的处理不同.wait:释放执行权,释放锁。sleep:释放执行权,不释放锁(不同中的代码必须拿到锁才能运行)

      3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围
         synchronized(x){
              x.notify()
             //或者wait()
         }
          4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

  • 相关阅读:
    QT 捕获事件(全局拦截)
    QT语言翻译
    QT,QLabel添加超链接
    解决VS+Qt不生成moc文件问题
    c++编译错误:invalid new-expression of abstract class type
    C++ 异常处理
    MATLAB 随机生成互不重叠的多个矩形
    sequential minimal optimization,SMO for SVM, (MATLAB code)
    How to decide on the correct number of clusters?
    python 将数据随机分为训练集和测试集
  • 原文地址:https://www.cnblogs.com/LO-ME/p/3574244.html
Copyright © 2011-2022 走看看