java中的并发工具辅助类

 

java中的并发工具类

一:等待多线程完成的CountDownLatch

CountDownLatch容许一个或多个线程等待其余线程完成操做。java

package com.fuzhulei;
import java.util.concurrent.*;

/**
* 减法计数器,主要是countDown(计数器1) 和 await(阻塞)方法,只有当计数器减为0的时候,当前线程才能够往下继续执行。
* 主要用于容许一个或多个线程等待其余线程完成操做
* @author Huxudong
* @createTime 2020-04-05 00:04:36
**/
public class CountDownDemo {
  public static void main(String[] args) throws InterruptedException {
      /** 使用其构造函数,建立一个数值为6的计数器 */
      CountDownLatch countDownLatch = new CountDownLatch(6);
      /** 自定义线程池使用 */
      ExecutorService pool = new ThreadPoolExecutor(
              6,   // 核心线程池大小
              9, // 最大线程池的大小(根据是IO密集型,仍是CPU密集型来肯定大小)
              3L,   // 超时等待时间
              TimeUnit.SECONDS,   // 时间的单位
              new LinkedBlockingQueue<>(5), // 阻塞队列是哪种
              Executors.defaultThreadFactory(),     // 默认线程建立工厂
              new ThreadPoolExecutor.AbortPolicy()   // 四大拒绝策略,选择一种
      );
      try{
          for (int i = 0; i < 6; i++) {
              /** 这个线程的提交,没有返回值的任务 */
              pool.execute(()->{
                  countDownLatch.countDown();
                  System.out.println(Thread.currentThread().getName()+"执行一次减法");
              });

          }
      } catch(Exception e) {
          e.printStackTrace();
      } finally {
          /** 关闭线程池 */
          pool.shutdown();
      }

      countDownLatch.await();
      System.out.println("执行完成了");

  }
}

正确执行结果:数据库

 

可是若是咱们设置计数器的容量大于6的话(相对于个人程序而言),就会被阻塞在那里多线程

 

会发现 执行完成了 没有被打印出来,并且程序一直没有中止,这个时候就是由于计数器没有归0,因此当前线程被阻塞,不能向下面继续进行。并发

 

二:同步屏障CyclicBarrier

CyclicBarrier的翻译大体就是可循环的屏障。它主要的做用就是让一组线程到达一个屏障(也能够叫作同步点)时被阻塞,直到最后一份线程到达屏障时,屏障才会开门,全部被屏障拦截的线程才会继续运行。ide

package com.fuzhulei;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
* CyclicBarrier是一个加法计数器,即同步屏障,可循环的屏障,让一组线程到达一个屏障(也能够叫作同步点)时被阻塞,直到最后一个线程到达屏障,达到了一开始初始化的屏障的数值,
* 屏障才能够打开门,全部被拦截的线程才能够继续工做,主要是经过调用await方法来实现的
* @author Huxudong
* @createTime 2020-04-04 22:53:50
**/
public class CyclicBarrierDemo {
  public static void main(String[] args) {
      CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
      new Thread(()->{

          try {
              cyclicBarrier.await();
          } catch (InterruptedException e) {
              e.printStackTrace();
          } catch (BrokenBarrierException e) {
              e.printStackTrace();
          }
          System.out.println("线程A已经到达屏障");
      },"A").start();

      new Thread(()->{
          try {
              cyclicBarrier.await();
          } catch (InterruptedException e) {
              e.printStackTrace();
          } catch (BrokenBarrierException e) {
              e.printStackTrace();
          }
          System.out.println("线程B已经到达屏障");
      },"B").start();

      new Thread(()->{
          try {
              cyclicBarrier.await();
          } catch (InterruptedException e) {
              e.printStackTrace();
          } catch (BrokenBarrierException e) {
              e.printStackTrace();
          }
          System.out.println("线程C已经到达屏障");
      },"C").start();


  }
}

执行的结果以下:函数

 

 

 

可是若是把定义的容量大于3(相对于个人程序而言),就会发现什么都不会输出了,看截图工具

 

 

 

而且程序一直尚未中止,这就是屏障起到了做用,由于屏障要求至少须要4个(假设),可是此时只有三个线程到达,因此不知足,屏障就一直阻拦不放路,那么全部的线程也就被阻塞不能向下面继续运行,除非知道第四个过来,知足条件才会运行。ui

 

三:控制并发线程数的Semaphore

用来控制同时访问特定资源的线程数量,经过协调各个线程,以保证合理的使用公用的资源。spa

package com.fuzhulei;

import java.util.concurrent.*;

/**
* 用来控制同时访问特定资源的线程数量,经过协调各个线程,以保证合理的使用公用的资源
* @author Huxudong
* @createTime 2020-04-04 23:45:29
**/
public class SemaphoreDemo {
  public static void main(String[] args) {
      Semaphore semaphore = new Semaphore(5);
      ExecutorService pool = new ThreadPoolExecutor(
              10,
              20,
              3L,
              TimeUnit.SECONDS,
              new LinkedBlockingQueue<>(20),
              Executors.defaultThreadFactory(),
              new ThreadPoolExecutor.AbortPolicy());

      try{
          for (int i = 0; i < 60; i++) {
              pool.execute(() ->{
                  try {
                      semaphore.acquire();
                      System.out.println(Thread.currentThread().getName()+"限流成功");
                      semaphore.release();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
          }
      } catch(Exception e) {
          e.printStackTrace();
      } finally {
          pool.shutdown();
      }
  }
}

执行的结果以下:线程

 

 

 

例如:数据库资源,假如须要读取几十万个数据的文件,由于都是IO密集型任务,因此开了2倍的处理器+1个线程数(IO密集型,因此线程能够多一些,让cpu忙起来,由于IO操做的时候,不多操做Cpu)

可是若是读到内存后,还须要存储到数据库中,可是数据库链接咱们设置的加入就10个,因此咱们必须控制只有10个线程能够同时访问数据库链接保存数据,不然会报错没法链接数据库异常。

相关文章
相关标签/搜索