线程间的通信_多生产者多消费者问题_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不需要捕获异常

posted @ 2014-02-28 19:59  胡椒粉hjf  阅读(220)  评论(0编辑  收藏  举报