1、减少计数CountDownLatch
案例演示:班长等待班上的6位同学离开后关上门。
此种情况会出现错误…….
public class CountDownLatchDemo {public static void main(String[] args) {for(int i=1;i<=6;i++){new Thread(()->{System.out.println(Thread.currentThread().getName()+"号同学离开了教室");},String.valueOf(i)).start();}System.out.println(Thread.currentThread().getName()+"班长关门了");}}
1号同学离开了教室3号同学离开了教室main班长关门了2号同学离开了教室4号同学离开了教室5号同学离开了教室6号同学离开了教室
解决方案:使用CountDownLatch
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {//创建CountDownLatch对象,设置初始值CountDownLatch countDownLatch=new CountDownLatch(6);//6个随机线程代表6个随机离开的学生for(int i=1;i<=6;i++){new Thread(()->{System.out.println(Thread.currentThread().getName()+"号同学离开了教室");//每离开一位同学计数器便减1countDownLatch.countDown();},String.valueOf(i)).start();}//当计数器的值不为0时,则main线程等待countDownLatch.await();System.out.println(Thread.currentThread().getName()+"班长关门了");}}
2、循环栅栏CyclicBarrier
案例:集齐七龙珠召唤神龙一样的道理,给线程设置好目标,当线程的数量达到之后,即会执行成功需要进行的操作。
public class CyclicBarrierDemo {private static final int NUMBER=7;public static void main(String[] args) {//创建CyclicBarrier对象,设置数量以及目标达到后需要进行的操作CyclicBarrier cyclicBarrier= new CyclicBarrier(NUMBER,()->{System.out.println("七龙珠召唤神龙");});for(int i=1;i<=7;i++){new Thread(()->{try {System.out.println(Thread.currentThread().getName()+"颗龙珠");//未收集完则等待cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}},String.valueOf(i)).start();}}}
3、信号灯Semaphore
案例:6个线程去抢占车位,并且在占用车位一定的时间后再离开。
public class SemaphoreDemo {public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);for (int i = 1; i <= 6; i++) {new Thread(() -> {try {//抢占车位semaphore.acquire();System.out.println(Thread.currentThread().getName() + ":抢占到车位");//随机设置占用车位的时间1-5秒TimeUnit.SECONDS.sleep(new Random().nextInt(5));System.out.println(Thread.currentThread().getName() + ":离开了车位");} catch (InterruptedException e) {e.printStackTrace();} finally {//释放车位semaphore.release();}}, String.valueOf(i)).start();}}}
