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個線程能夠同時訪問數據庫鏈接保存數據,不然會報錯沒法鏈接數據庫異常。

相關文章
相關標籤/搜索