1. 程式人生 > 程式設計 >Java併發工具輔助類程式碼例項

Java併發工具輔助類程式碼例項

java中的併發工具類

一:等待多執行緒完成的CountDownLatch

CountDownLatch允許一個或多個執行緒等待其他執行緒完成操作。

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("執行完成了");
​
  }
}

正確執行結果:

Java併發工具輔助類程式碼例項

但是如果我們設定計數器的容量大於6的話(相對於我的程式而言),就會被阻塞在那裡

Java併發工具輔助類程式碼例項

會發現執行完成了 沒有被打印出來,而且程式一直沒有停止,這個時候就是因為計數器沒有歸0,所以當前執行緒被阻塞,不能向下面繼續進行。

二:同步屏障CyclicBarrier

CyclicBarrier的翻譯大致就是可迴圈的屏障。它主要的作用就是讓一組執行緒到達一個屏障(也可以叫做同步點)時被阻塞,直到最後一份執行緒到達屏障時,屏障才會開門,所有被屏障攔截的執行緒才會繼續執行。

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();
​
​
  }
}

執行的結果如下:

Java併發工具輔助類程式碼例項

但是如果把定義的容量大於3(相對於我的程式而言),就會發現什麼都不會輸出了,看截圖

Java併發工具輔助類程式碼例項

並且程式一直還沒有停止,這就是屏障起到了作用,因為屏障要求至少需要4個(假設),但是此時只有三個執行緒到達,所以不滿足,屏障就一直阻攔不放路,那麼所有的執行緒也就被阻塞不能向下面繼續執行,除非知道第四個過來,滿足條件才會執行。

三:控制併發執行緒數的Semaphore

用來控制同時訪問特定資源的執行緒數量,通過協調各個執行緒,以保證合理的使用公用的資源。

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();
    }
  }
}

執行的結果如下:

Java併發工具輔助類程式碼例項

例如:資料庫資源,假如需要讀取幾十萬個數據的檔案,因為都是IO密集型任務,所以開了2倍的處理器+1個執行緒數(IO密集型,所以執行緒可以多一些,讓cpu忙起來,因為IO操作的時候,很少操作Cpu)

但是如果讀到記憶體後,還需要儲存到資料庫中,但是資料庫連線我們設定的加入就10個,所以我們必須控制只有10個執行緒可以同時訪問資料庫連線儲存資料,否則會報錯無法連線資料庫異常。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。