Lock中使用Condition实现等待通知

  • Condition类有很好的灵活性,可以实现多路通知功能,一个Lock对象中可以创建多个Condition对象实例,线程对象可以注册在指定的Condition中,进而有选择的进行线程通知,在调度线程上更加灵活
  • wait与notify/notifyAll进行等待通知时,被通知的线程是随机的,但是Condition与Lock结合的通知是有选择性的通知
  • synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有线程对象都注册在一个Condition对象身上,线程开始notifyAll时,需要通知所有的WAITING线程,没有选择性,会出现很大的效率问题
 1 public class MyService {
 2     private Lock lock = new ReentrantLock();
 3     public Condition condition = lock.newCondition();
 4     public void await(){
 5         try {
 6             lock.lock();
 7             System.out.println("await时间为"+System.currentTimeMillis());
 8             condition.await();
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         } finally {
12             lock.unlock();
13         }
14     }
15 
16     public void signal(){
17         try {
18             lock.lock();
19             System.out.println("signal时间为"+System.currentTimeMillis());
20             condition.signal();
21         } finally {
22             lock.unlock();
23         }
24     }
25 }
 1 public class MyThread extends Thread {
 2     private MyService service;
 3 
 4     public MyThread(MyService service) {
 5         this.service = service;
 6     }
 7 
 8     @Override
 9     public void run() {
10         service.await();
11     }
12 }
 1 public class Run {
 2     public static void main(String[] args) {
 3         try {
 4             MyService service = new MyService();
 5             MyThread mt = new MyThread(service);
 6             mt.start();
 7             Thread.sleep(3000);
 8             service.signal();
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12     }
13 }

-------------------------------------------------------打印输出-------------------------------------------------------

await时间为1537949157830
signal时间为1537949160830

Condition类中的await方法相当于Object类中的wait方法

Condition类中的signal/signalAll方法相当于Object类中的notify/notifyAll方法

案例2

 1 public class MyService {
 2     private Lock lock = new ReentrantLock();
 3     public Condition condition = lock.newCondition();
 4 
 5     public void awaitA(){
 6         try {
 7             lock.lock();
 8             System.out.println("begin awaitA时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
 9             condition.await();
10             System.out.println("end awaitA时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
11         } catch (InterruptedException e) {
12             e.printStackTrace();
13         } finally {
14             lock.unlock();
15 
16         }
17     }
18 
19     public void awaitB(){
20         try {
21             lock.lock();
22             System.out.println("begin awaitB时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
23             condition.await();
24             System.out.println("end awaitB时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
25         } catch (InterruptedException e) {
26             e.printStackTrace();
27         } finally {
28             lock.unlock();
29         }
30     }
31 
32     public void signalAll(){
33         try {
34             lock.lock();
35             System.out.println("signalAll时间为"+System.currentTimeMillis()+ " ThreadName="+Thread.currentThread().getName());
36             condition.signalAll();
37         } finally {
38             lock.unlock();
39         }
40     }
41 }

线程

 1 public class ThreadA extends Thread {
 2     private MyService service;
 3 
 4     public ThreadA(MyService service) {
 5         this.service = service;
 6     }
 7 
 8     @Override
 9     public void run() {
10         service.awaitA();
11     }
12 }
13 -------------------------------------------------
14 public class ThreadB extends Thread {
15     private MyService service;
16 
17     public ThreadB(MyService service) {
18         this.service = service;
19     }
20 
21     @Override
22     public void run() {
23         service.awaitB();
24     }
25 }
 1 public class Run {
 2     public static void main(String[] args) throws InterruptedException {
 3         MyService service = new MyService();
 4         ThreadA a = new ThreadA(service);
 5         a.setName("A");
 6         ThreadB b = new ThreadB(service);
 7         b.setName("B");
 8         a.start();
 9         b.start();
10         Thread.sleep(3000);
11         service.signalAll();
12     }
13 }

-------------------------------------------------------打印输出-------------------------------------------------------

begin awaitA时间为1537951494924 ThreadName=A
begin awaitB时间为1537951494925 ThreadName=B
signalAll时间为1537951497924 ThreadName=main
end awaitA时间为1537951497924 ThreadName=A
end awaitB时间为1537951497925 ThreadName=B

线程A和B都被唤醒了


使用多个Condition实现通知部分线程

想要单独唤醒部分线程,就需要使用多个Condition对象,先对线程进行分组,Condition对象可以唤醒部分指定线程,有助于提高程序运行效率

 1 public class MyService {
 2     private Lock lock = new ReentrantLock();
 3     public Condition conditionA = lock.newCondition();
 4     public Condition conditionB = lock.newCondition();
 5 
 6     public void awaitA(){
 7         try {
 8             lock.lock();
 9             System.out.println("begin awaitA时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
10             conditionA.await();
11             System.out.println("--end awaitA时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         } finally {
15             lock.unlock();
16         }
17     }
18 
19     public void awaitB(){
20         try {
21             lock.lock();
22             System.out.println("begin awaitB时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
23             conditionB.await();
24             System.out.println("--end awaitB时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
25         } catch (InterruptedException e) {
26             e.printStackTrace();
27         } finally {
28             lock.unlock();
29         }
30     }
31 
32     public void signAll_A(){
33         try {
34             lock.lock();
35             System.out.println("signAll_A时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
36             conditionA.signalAll();
37         } finally {
38             lock.unlock();
39         }
40     }
41 
42     public void signAll_B(){
43         try {
44             lock.lock();
45             System.out.println("signAll_B时间为"+System.currentTimeMillis()+" ThreadName="+Thread.currentThread().getName());
46             conditionB.signalAll();
47         } finally {
48             lock.unlock();
49         }
50     }
51 }

线程

扫描二维码关注公众号,回复: 3362358 查看本文章
 1 public class ThreadA extends Thread {
 2     private MyService service;
 3 
 4     public ThreadA(MyService service) {
 5         this.service = service;
 6     }
 7 
 8     @Override
 9     public void run() {
10         service.awaitA();
11     }
12 }
13 -----------------------------------------------
14 public class ThreadB extends Thread {
15     private MyService service;
16 
17     public ThreadB(MyService service) {
18         this.service = service;
19     }
20 
21     @Override
22     public void run() {
23         service.awaitB();
24     }
25 }
 1 public class Run {
 2     public static void main(String[] args) throws InterruptedException {
 3         MyService service = new MyService();
 4         ThreadA a = new ThreadA(service);
 5         a.setName("A");
 6         ThreadB b = new ThreadB(service);
 7         b.setName("B");
 8         a.start();
 9         b.start();
10         Thread.sleep(3000);
11         service.signAll_A();
12     }
13 }

-------------------------------------------------------打印输出-------------------------------------------------------

begin awaitA时间为1537952328573 ThreadName=A
begin awaitB时间为1537952328573 ThreadName=B
signAll_A时间为1537952331572 ThreadName=main
--end awaitA时间为1537952331572 ThreadName=A

线程A被唤醒了,但是线程B仍然在等待

猜你喜欢

转载自www.cnblogs.com/qf123/p/9708244.html