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的翻譯大體就是可循環的屏障。它主要的做用就是讓一組線程到達一個屏障(也能夠叫作同步點)時被阻塞,直到最後一份線程到達屏障時,屏障纔會開門,全部被屏障攔截的線程纔會繼續運行。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
用來控制同時訪問特定資源的線程數量,經過協調各個線程,以保證合理的使用公用的資源。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)