本文共 2425 字,大约阅读时间需要 8 分钟。
参考了很多网上的资料和视频,发现Condition监视器的精准唤醒例子都需要使用标识符,但实际上使用标识符的话是可以不用到Condition监视器的直接用Object监视器(wait/notify)来执行的。
个人感觉这些例子举得都不好,所以自己写了不用标识符的情况下可以直接用Condition来实现精准唤醒的例子,也从中发现了一些问题,具体已经写在注释。
public class TestJUC05 { public static void main(String[] args) throws InterruptedException { Data data = new Data(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.B(); } },"BB").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.C(); } },"CC").start(); //让A线程最后最后执行才对下一个线程的condition监视器唤醒起效,才能进入一个循环, //否则一开始A线程执行得太快,有可能会导致当B线程的监视器还没等待的时候已经执行唤醒, //然后之后就全部线程都无法唤醒,进入死循环 Thread.sleep(1000); new Thread(()->{ for (int i = 0; i < 10; i++) { data.A(); } },"AA").start(); }}class Data{ private Lock lock=new ReentrantLock(); Condition condition1=lock.newCondition(); Condition condition2=lock.newCondition(); Condition condition3=lock.newCondition(); //该标识符用于标识A线程是否第一次执行 int number=0; public void A(){ lock.lock(); try { //第一次不用等待直接执行,之后的都需要等待线程C的唤醒 if (number!=0) { condition1.await(); } System.out.println("AAAAAAAAAAAAAA"); number++; //让BC线程先跑都进入等待,才能对B线程进行唤醒 condition2.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void B(){ lock.lock(); try { condition2.await(); System.out.println("BBBBBBBBBBBBBBBB"); condition3.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void C(){ lock.lock(); try { condition3.await(); System.out.println("CCCCCCCCCCCCCCCC"); condition1.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }}
//运行结果AAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC......
转载地址:http://rhru.baihongyu.com/