• 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 }

    线程

     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仍然在等待

  • 相关阅读:
    POJ 3276 Face The Right Way
    POJ 3061 Subsequence
    HDU 2104 hide handkerchief
    GCJ Crazy Rows
    HDU 1242 Rescue
    激光炸弹:二维前缀和
    I Hate It:线段树:单点修改+区间查询
    承压计算:模拟+double
    等差素数列:线性筛+枚举
    Period :KMP
  • 原文地址:https://www.cnblogs.com/qf123/p/9708244.html
Copyright © 2020-2023  润新知