juc下常用的五个高并发工具

1、CountDownLatch:同步计数器
当CountDownLatch的count计数>0时,await()会造成线程阻塞,当使用countDown()让count-- == 0时,线程结束阻塞。 如果想让其他线程执行完指定程序,其他所有程序都执行结束后再执行,这时可以用CountDownLatch,但计数无法被重置,如果需要重置计数,请考虑使用 CyclicBarrier。下面demo演示了当所有线程执行完任务后。

public class CountDownLatchDemo implements Runnable {

   private CountDownLatch begin;
   //观察end的count为0时,会使当前线程退出阻塞
   private CountDownLatch end;
   //用来模拟子线程执行的任务
   private int index = 10;

   public CountDownLatchDemo(CountDownLatch begin, CountDownLatch end) {
       this.begin = begin;
       this.end = end;
   }

   //这里要使用同步synchronized
   synchronized  public void run(){
       try {
           begin.await();
           index--;
           System.out.println(Thread.currentThread().getName() + ":执行完任务了,  index: " + index);
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           end.countDown();
       }
   }

   public static void main(String[] args) throws InterruptedException {
       CountDownLatch begin = new CountDownLatch(1);
       CountDownLatch end = new CountDownLatch(10);
       CountDownLatchDemo cdlDemo = new CountDownLatchDemo(begin, end);
       System.out.println("所有线程开始执行任务....");
       for (int i = 0; i < 10; i++) {
           new Thread(cdlDemo).start();
       }
       //开始让所有线程工作
       begin.countDown();
       //
       end.await();
       System.out.println("所有线程完成任务,可以开始做其它想做的事 了....");
   }
}

2、CyclicBarrier: 线程屏障的功能
可以协同多个线程,让多个线程在这个屏障前等到,直到所有线程都到达了这个屏障时,再一起执行后面的操作。下面demo创建11个线程,前面每一个线程使用await()都会使当前线程阻塞,直到最后一个线程使用await()会使11个线程全部退出阻塞。

public class CyclicBarrierDemo implements Runnable {

    private CyclicBarrier cyclicBarrier;
    private int index ;

    public CyclicBarrierDemo(CyclicBarrier cyclicBarrier, int index) {
        this.cyclicBarrier = cyclicBarrier;
        this.index = index;
    }

    public void run() {
        try {
            System.out.println("index: " + index);
            index--;
            cyclicBarrier.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(11);
        for (int i = 0; i < 10; i++) {
            new Thread(new CyclicBarrierDemo(cyclicBarrier, i)).start();
        }
        cyclicBarrier.await();
        System.out.println("全部到达屏障....");
    }
}

3、Exchanger:用来使两个线程交换数据。
当一个线程运行到exchange()方法时会阻塞,另一个线程运行到exchange()时,二者交换数据,然后执行后面的程序。

public class ExchangerDemo implements Runnable {

    private Exchanger> exchanger;
    private Map info;

    public ExchangerDemo (Exchanger> exchanger, Map info) {
        this.exchanger = exchanger;
        this.info = info;
    }

    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + "交换前的值是:" + info.toString() );
            Map result = exchanger.exchange(info);
            System.out.println(Thread.currentThread().getName() + "交换后的值是:" + result.toString() );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Map aMap = new HashMap();
        Map bMap = new HashMap();
        aMap.put("a", "aaa");
        aMap.put("b", "bbb");
        aMap.put("c", "ccc");
        bMap.put("1", "111");
        bMap.put("2", "222");
        bMap.put("3", "333");
        Exchanger> exchanger = new Exchanger>();
        new Thread(new ExchangerDemo(exchanger, aMap)).start();
        new Thread(new ExchangerDemo(exchanger, bMap)).start();
    }
}

4、Semaphore:控制信号量的个数,构造时传入个数。总数就是控制并发的数量。
线程执行前用acquire()方法获得信号,执行完通过release()方法归还信号量。如果可用信号为0,acquire就会造成阻塞,等待release释放信号。作用就是只让指定个数的线程(随机选择或先来后到)并行。

public class SemaphoreDemo implements Runnable {

    private Semaphore sema;

    public SemaphoreDemo (Semaphore semaphore) {
        this.sema = semaphore;
    }

    public void run() {
        try {
            sema.acquire();
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread().getName() + ": 执行完: " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            sema.release();
        }
    }

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo(semaphore);
        for (int i = 0; i < 10; i++) {
            new Thread(semaphoreDemo).start();
        }
    }
}

5、Future:接口,FutureTask是它的实现类,配合线程池来一起工作,将任务交给线程池去处理。

public class FutureDemo {

    public static void main(String[] args) throws Exception {
        Future task = new FutureTask(new Callable() {
            @Override
            public Integer call() {
                return 1+2+3+4;
            }
        });

        new Thread((Runnable) task).start();
        System.out.println("start.........");
        TimeUnit.SECONDS.sleep(2);
        System.out.println("result: " + task.get());
    }
}

最后贴一个业务场景分别用CyclicBarrier和Future代码片段:
用CyclicBarrier实现

int size = executeMethods.length;
CyclicBarrier cyclicBarrier = new CyclicBarrier(size+1);
for (int i = 0; i < size; i++) {
    threadPool.execute(new CheckItemsTask(
            customerId, executeMethods[i], cyclicBarrier, CheckResultVO));
}
try {
    cyclicBarrier.await();
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (BrokenBarrierException e) {
    e.printStackTrace();
}
public class CheckItemsTask implements Runnable {

    String EXECUTE_PREFIX = Constant.EXECUTE_METHOD_START_STR;
    String SETTLE_PREFIX = Constant.SETTLE_METHOD_START_STR;

    private CyclicBarrier cyclicBarrier;
    private CheckResultVO checkResultVO;
    private String methodName;
    private Integer customerId;

    SettleOrderService settleOrderService = SpringUtils.getBean(SettleOrderService.class);
    Class c = settleOrderService.getClass();

    public CheckItemsTask(){}

    public CheckItemsTask(Integer customerId, String methodName,
                          CyclicBarrier cyclicBarrier, CheckResultVO checkResultVO){
        this.customerId = customerId;
        this.methodName = methodName;
        this.cyclicBarrier = cyclicBarrier;
        this.checkResultVO = checkResultVO;
    }

    synchronized public void run() {
        try{
            long startTime = System.currentTimeMillis();
            excuteCheckTask(methodName, checkResultVO);
            long endTime = System.currentTimeMillis();
            LogUtils.logger().info("该校验方法 executeMethodName={} 的执行时间为 time={}", EXECUTE_PREFIX+methodName, endTime-startTime);
        } finally {
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * @param methodName
     * @return
     */
    private void excuteCheckTask(String methodName, CheckResultVO checkResultVO){
        try {
            String executeMethodName = EXECUTE_PREFIX + methodName;
            if (StringUtils.equals(executeMethodName, "checkExistEffectiveContract") ||
                    StringUtils.equals(executeMethodName, "checkExistBusinessLeader")) {
                Method m = c.getDeclaredMethod(executeMethodName, Integer.class, CheckResultVO.class);
                m.invoke(settleOrderService, customerId, checkResultVO);
            } else {
                Method m = c.getDeclaredMethod(executeMethodName, Integer.class);
                boolean flag = (boolean) m.invoke(settleOrderService, customerId);
                String settleMethodName = SETTLE_PREFIX + methodName;
                setCheckValue(settleMethodName, flag);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param settleMethodName
     * @param isTrue
     */
    private void setCheckValue(String settleMethodName, boolean isTrue) {
        try {
            Class c = checkResultVO.getClass();
            Method m = c.getMethod(settleMethodName, Boolean.class);
            m.invoke(checkResultVO, isTrue);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

}

用Future实现

List> results = Lists.newArrayList();
for (int i = 0; i < size; i++) {
    results.add(threadPool.submit(new CheckItemsTaskS(
            customerId, executeMethods[i], CheckResultVO)));
}
results.stream().forEach(r -> {
    try {
        r.get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
});
public class CheckItemsTaskS implements Callable {
    String EXECUTE_PREFIX = Constant.EXECUTE_METHOD_START_STR;
    String SETTLE_PREFIX = Constant.SETTLE_METHOD_START_STR;

    private CheckResultVO checkResultVO;
    private String methodName;
    private Integer customerId;

    SettleOrderService settleOrderService = SpringUtils.getBean(SettleOrderService.class);
    Class c = settleOrderService.getClass();

    public CheckItemsTaskS(){}

    public CheckItemsTaskS(Integer customerId, String methodName, CheckResultVO checkResultVO){
        this.customerId = customerId;
        this.methodName = methodName;
        this.checkResultVO = checkResultVO;
    }

    @Override
    public Object call() throws Exception {
        long startTime = System.currentTimeMillis();
        excuteCheckTask(methodName, checkResultVO);
        long endTime = System.currentTimeMillis();
        LogUtils.logger().info("该校验方法 executeMethodName={} 的执行时间为 time={}", EXECUTE_PREFIX+methodName, endTime-startTime);
        return checkResultVO;
    }

    /**
     * @param methodName
     * @return
     */
    private void excuteCheckTask(String methodName, CheckResultVO checkResultVO){
        try {
            String executeMethodName = EXECUTE_PREFIX + methodName;
            if (StringUtils.equals(executeMethodName, "checkExistEffectiveContract") ||
                    StringUtils.equals(executeMethodName, "checkExistBusinessLeader")) {
                Method m = c.getDeclaredMethod(executeMethodName, Integer.class, CheckResultVO.class);
                m.invoke(settleOrderService, customerId, checkResultVO);
            } else {
                Method m = c.getDeclaredMethod(executeMethodName, Integer.class);
                boolean flag = (boolean) m.invoke(settleOrderService, customerId);
                String settleMethodName = SETTLE_PREFIX + methodName;
                setCheckValue(settleMethodName, flag);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param settleMethodName
     * @param isTrue
     */
    private void setCheckValue(String settleMethodName, boolean isTrue) {
        try {
            Class c = checkResultVO.getClass();
            Method m = c.getMethod(settleMethodName, Boolean.class);
            m.invoke(checkResultVO, isTrue);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

你可能感兴趣的:(Java)