1.CountDownLatch减少计数
2.CycliBarrier循环栅栏
3.Semaphore信号灯
对于第一种CountDownLatch
对于这个,当我们离开学校时,等每一个班的孩子走完了才能锁门
for (int i = 0; i < 7; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"号同学离开了学校");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+"锁门");
而结果就是,当锁门后,同学还有没有离开学校的
于是我们引入CountDownLatch
CountDownLatch countDownLatch = new CountDownLatch(7);//计数
//7个人离开学校
for (int i = 0; i < 7; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"号同学离开了学校");
countDownLatch.countDown();//计数减1
},String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"锁门");
现在结果一目了然
对于CyclicBarrier,我们用一个简单的例子来说
我们用一个简单的例子来讲,当我们要集齐7个龙珠,才能召唤神龙,但如果集齐6颗肯定不可以召唤神龙,会处于一直等待中
CyclicBarrier的构造器为如下所示,构造器中要实现Runnable接口,直接用Lambda表达式,当没有达到7时,则不执行Lambda中的语句,达到后再执行
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("集齐七颗龙珠,召唤神龙");
});
代码:
//7个人去收集龙珠
for (int i = 0; i < 7; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"号同学拿到了龙珠");
//等待
try {
cyclicBarrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
},String.valueOf(i)).start();
}
结果:
没达到如图:程序一直没结束,而Lambda表达式中的语句一直没有输出
Semaphore类似于操作系统中的pv操作
设置一个信号量,当信号量为0时,则处于等待状态,一个线程结束,则释放信号量,另一个线程则可以运行
用一个停车的例子来说,当只有3个停车位,但有6辆车要入库,则当1辆车进入,就占有一个,3个车进入后,则后面二点车不能进入必须等待有一辆车离开后才能进入
代码如下:
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
semaphore.acquire();//信号量的获得
System.out.println(Thread.currentThread().getName()+"号车入库");
TimeUnit.SECONDS.sleep(new Random().nextInt(5));//设置睡眠到五秒的随机数
System.out.println(Thread.currentThread().getName()+"号车离开了车位");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
semaphore.release();//信号的释放,必须在finally块中
}
},String.valueOf(i)).start();
}
结果: