没长正的技术专栏 勤动手、多思考

高并发之限制工具类

2018-08-03

阅读:


1. 限制

​ JUC提供了几个比较常用的并发工具类:CountDownLatch extend AQS、CyclicBarrier 包含 Lock对象、Semaphore extend AQS

1.1 CountDownLatch

​ countdownlatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作,执行完毕再执行。不可重置/不能重复使用从命名可以解读到 countdown 是倒数的意思,类似于我们倒计时的概念。countdownlatch 提供了两个方法,一个是 countDown,一个是 await, countdownlatch 初始化的时候需要传入一个整数,在这个整数倒数到 0 之前,调用了 await 方法的程序都必须要等待,然后通过 countDown 来倒数。

public static void main(String[] args) throws InterruptedException {
    
 	CountDownLatch countDownLatch=new CountDownLatch(3);
     new Thread(()->{
         System.out.println(""+Thread.currentThread().getName()+"-执行中");
         countDownLatch.countDown();
         System.out.println(""+Thread.currentThread().getName()+"-执行完毕");
     },"t1").start();
    
     new Thread(()->{
         System.out.println(""+Thread.currentThread().getName()+"-执行中");
         countDownLatch.countDown();
         System.out.println(""+Thread.currentThread().getName()+"-执行完毕");
     },"t2").start();
    
     new Thread(()->{
         System.out.println(""+Thread.currentThread().getName()+"-执行中");
         countDownLatch.countDown();
         System.out.println(""+Thread.currentThread().getName()+"-执行完毕");
     },"t3").start();
    
     countDownLatch.await();//等待执行完毕,类似Thread.join功能
     System.out.println("所有线程执行完毕");
}
//从代码的实现来看,有点类似 join 的功能,但是比 join 更加灵活。CountDownLatch 构造函
//数会接收一个 int 类型的参数作为计数器的初始值,当调用 CountDownLatch 的 countDown
//方法时,这个计数器就会减一。
//通过 await 方法去阻塞去阻塞主流程

2021-11-29_CountDownLatch分析

//凡事涉及到需要指定某个任务在执行之前,要等到前置任务执行完毕之后才执行的场景,都可以使用 CountDownLatch

1.2 CyclicBarrier

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门 , 所有被屏障拦截的线程才会继续工 作 。

1.2.1 使用场景

​ 当存在需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用 CyclicBarrier。可重置reset,重复使用

public class DataImportThread extends Thread{
     private CyclicBarrier cyclicBarrier;
     private String path;
 public DataImportThread(CyclicBarrier cyclicBarrier, String path) {
     this.cyclicBarrier = cyclicBarrier;
     this.path = path;
 }
    
 @Override
 public void run() {
 		System.out.println("开始导入:"+path+"位置的数据");
         try {
             cyclicBarrier.await();//阻塞
         } catch (InterruptedException e) {
             e.printStackTrace();
         } catch (BrokenBarrierException e) {
             e.printStackTrace();
         }
     } 
}
//CycliBarrierDemo
public class CycliBarrierDemo extends Thread{
     @Override
     public void run() {
        System.out.println("开始进行数据分析");
     }
     public static void main(String[] args) {
         CyclicBarrier cycliBarrier=new
         CyclicBarrier(3,new CycliBarrierDemo());
         new Thread(new DataImportThread(cycliBarrier,"file1")).start();
         new Thread(new DataImportThread(cycliBarrier,"file2")).start();
         new Thread(new DataImportThread(cycliBarrier,"file3")).start();
     } 
}

1.3 Semaphore

semaphore 也就是我们常说的信号灯,semaphore 可以控制同时访问的线程个数,通过acquire 获取一个许可,如果没有就等待,通过 release 释放一个许可。可释放release,然后重复使用

public class Test {
     public static void main(String[] args) {
         Semaphore semaphore=new Semaphore(5);
         for(int i=0;i<10;i++){
         	new Car(i,semaphore).start();
         }
     }
    static class Car extends Thread{
         private int num;
         private Semaphore semaphore;
        
         public Car(int num, Semaphore semaphore) {
             this.num = num;
             this.semaphore = semaphore;
         }
         public void run(){
             try {
                 semaphore.acquire();//获取一个许可
                 System.out.println("第"+num+"占用一个停车位");
                 TimeUnit.SECONDS.sleep(2);
                 System.out.println("第"+num+"俩车走喽");
                 semaphore.release();
             } catch (InterruptedException e) {
             	e.printStackTrace();
             }
         }
     } 
}

参考:


欢迎拍砖,多多交流,转载请注明出处:[没长正的技术专栏](http://blog.meizhangzheng.com) 如涉及侵权问题,请发送邮件到xsj34567@163.com,如情况属实本人将会尽快删除。


下一篇 JVM基础

Comments

Content