(转)Java多线程技术 -- 等待唤醒机制(二)

原博客网站:http://blog.csdn.net/watermusicyes/article/details/8804743

 

这篇主要讲解,JDK1.5以后,对多线程技术的改进。那么,为什么要对之前的技术进行改进呢,在上篇中的多生产者,多消费者例子中,当有一个线程在执行时,其他的线程在申请对锁的拥有权是,会不断的进行判断,这样会降低降低程序的性能。为此,JDK 1.5 以后,对多线程技术做了改进。

JDK1.5后出现的新的接口和类:Lock:比同步函数和同步代码块要好一些。同步函数还是同步代码块所做的都是隐式的锁操作。并且,同步函数或者同步代码块使用的锁和监视器是同一个。

 

Lock接口:是将锁进行单独对象的封装。而且提供了对锁对象很多功能。  比如:lock()获取锁,unlock()释放锁。  Lock对锁的操作都是显示操作。所以它的出现要比同步函数或者同步代码块明确的多,更符合面向对象思想。

 

简单一句话:Lock接口的出现替代同步。

下面将上述的生产者消费者 代码,进行 Lock 改写:

 1 class Resource
 2 {
 3 
 4     private String name;
 5     private int count = 1;
 6     private boolean flag;
 7     //创建一个锁对象。
 8     private final Lock lock = new ReentrantLock();
 9     //获取一个该锁上的监视器。 
10     private Condition con = lock.newCondition();
11     public  void set(String name)//  
12     {
13         //获取锁。
14         lock.lock();
15         try
16         {
17         
18             while(flag)
19                 try{con.await();}catch(InterruptedException e){}
20             this.name = name + count; 
21 
22             count++;
23             System.out.println(Thread.currentThread().getName()+".....生产者......"+this.name);
24                                                                                             
25             flag = true;
26             con.signalAll();
27         }
28         finally
29         {
30             //释放锁。
31             lock.unlock();
32         }
33     }
34 
35     public  void get()//  
36     {
37         lock.lock();
38         try
39         {
40             
41         
42             while(!flag)
43                 try{con.await();}catch(InterruptedException e){}
44 
45             System.out.println(Thread.currentThread().getName()+".........消费者......"+this.name);
46             flag = false;
47             con.signalAll();
48         }
49         finally
50         {
51             lock.unlock();
52         }
53     }
54 }
View Code

这样,对锁的操作显而易见。清晰的很。

 

 

原来在同步中,锁和监视器是同一个对象。现在,升级后,锁是一个单独的对象。而且将监视器的方法也单独封装到了一个对象中。这个对象就是升级后Condition.

升级后,都进行了单独的封装。锁被封装成了Lock对象。监视器方法都被封装到了Condition对象(监视器对象)中。 说白了,Lock替代了同步,Condition替代了Object中的监视器方法。

Condition中提供了监视器的方法:awati().signal(),signalAll();

那么,该  如何让锁和监视器产生联系呢?

  直接通过Lock接口中的newCondition()方法就可以获取到能绑定到该Lock对象的上的监视器对象Condition。

 

之前,我们为了解决,1,本方唤醒了本方。2,被唤醒的本方没有判断标记。这两个问题时,将if 改为  while , 并且用了 notifyAll() ,这种解决方案效率低,因为还会唤醒本方。

 

 有了新特性Lock,Condition。就可以解决这个问题了。之前是有两个锁嵌套,容易死锁,现在方案是只有锁,但是锁上可以加入多个监视器 :一个监视生产者,一个监视消费者。

改写后的代码为:

 1 class Resource
 2 {
 3 
 4     private String name;
 5     private int count = 1;
 6     private boolean flag;
 7     //创建一个锁对象。
 8     private final Lock lock = new ReentrantLock();
 9     //创建一个生产者的监视器。
10     private Condition producer_con = lock.newCondition();
11     //创建一个消费者监视器。
12     private Condition consumer_con = lock.newCondition();
13     
14     public  void set(String name)//  
15     {
16         //获取锁。
17         lock.lock();
18         try
19         {
20         
21             while(flag)
22                 try{producer_con.await();}catch(InterruptedException e){}
23             this.name = name + count;
24 
25             count++;
26 
27             System.out.println(Thread.currentThread().getName()+".....生产者......"+this.name);                                                                                            
28             flag = true;
29             consumer_con.signal();
30         }
31         finally
32         {
33             //释放锁。
34             lock.unlock();
35         }
36     }
37 
38     public  void get()//  
39     {
40         lock.lock();
41         try
42         {
43                     
44             while(!flag)
45                 try{consumer_con.await();}catch(InterruptedException e){}
46 
47             System.out.println(Thread.currentThread().getName()+".........消费者......"+this.name);
48             flag = false;
49             producer_con.signal();
50         }
51         finally
52         {
53             lock.unlock();
54         }
55     }
56 }
View Code

 

posted @ 2015-09-07 17:37  JonthanJ  阅读(123)  评论(0)    收藏  举报