欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)包線程池ThreadPoolExecutor的實現

 更新時間:2022年04月02日 10:42:39   作者:派大大大星  
本文主要介紹了Java并發(fā)包線程池ThreadPoolExecutor的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

線程池主要解決兩個問題:一是當執(zhí)行大量異步任務時線程池能夠提供較好的性能。在不使用線程池時,每當需要執(zhí)行異步任務時直接new一個線程來運行,而線程的創(chuàng)建和銷毀都是需要開銷的。線程池里面的線程是可復用的,不需要每次執(zhí)行異步任務時都重新創(chuàng)建和銷毀線程。二是線程池提供了一種資源限制和管理手段,比如可以限制線程的個數,動態(tài)新增線程等。每個ThreadPoolExecutor也保留了一些基本的統(tǒng)計數據,比如當前線程池完成的任務數目等。

我們首先來看一下類圖

Excecutor是一個工具類,里面提供了許多靜態(tài)方法,這些方法根據用戶選擇返回不同的線程池實例。ThreadPool繼承了AbstractExecutorService。

下面我們看一下源碼,

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY ? = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
private static final int RUNNING ? ?= -1 << COUNT_BITS;
private static final int SHUTDOWN ? = ?0 << COUNT_BITS;
private static final int STOP ? ? ? = ?1 << COUNT_BITS;
private static final int TIDYING ? ?= ?2 << COUNT_BITS;
private static final int TERMINATED = ?3 << COUNT_BITS;

成員變量ctl是一個Integer的原子變量,用來記錄當前線程池狀態(tài)和線程池中的線程個數,有點類似于ReentrantReadWriteLock使用一個變量來保存兩種信息。

線程池一共有五種狀態(tài):

  • RUNNING:能接受新任務,并且處理阻塞隊列里面的任務
  • SHUTDOWN:拒絕接受新任務但是處理阻塞隊列里的任務
  • STOP:拒絕新任務并且拋棄阻塞隊列里的任務
  • TIDYING:所有任務都執(zhí)行完(包含阻塞隊列里面的任務)后當前線程池活動線程數為0,將要調用terminated方法。
  • TERMINATED:終止狀態(tài)。terminated方法調用完成以后的狀態(tài)。

線程池狀態(tài)轉換如下:

  • RUNNING->SHUTDOWN:顯示調用shutdown方法,或者隱式調用finalize()方法里的shutdown()方法。
  • RUNNINGSHUTDOWN->STOP:顯示調用shutdown方法
  • SHUTDOWN->TIDYING:當線程池和任務隊列都為空時
  • STOP->TIDYING:當線程池為空時
  • TIDYING->TERMINATED:Terminated() hook方法執(zhí)行完畢時

線程池的使用

合理利用線程池能夠帶來三個好處:

  • 降低資源消耗。減少了創(chuàng)建和銷毀線程的次數,每個工作線程都可以被重復利用,可執(zhí)行多個任務。
  • 提高響應速度。當任務到達時,任務可以不需要的等到線程創(chuàng)建就能立即執(zhí)行。
  • 提高線程的可管理性??梢愿鶕到y(tǒng)的承受能力,調整線程池中工作線線程的數目,防止因為消耗過多的內存,而把服務器累趴下(每個線程需要大約1MB內存,線程開的越多,消耗的內存也就越大,最后死機)。

在java.util.concurrent.Executors線程工廠類里面提供了一些靜態(tài)工廠,生成一些常用的線程池。官方建議使用Executors工程類來創(chuàng)建線程池對象。
Executors類中有個創(chuàng)建線程池的方法如下:

  • public static ExecutorService newFixedThreadPool(int nThreads):返回線程池對象。(創(chuàng)建的是有界線程池,也就是池中的線程個數可以指定最大數量)

獲取到了一個線程池ExecutorService 對象,那么怎么使用呢,在這里定義了一個使用線程池對象的方法如下:

  • public Future<?> submit(Runnable task):獲取線程池中的某一個線程對象,并執(zhí)行

Future接口:用來記錄線程任務執(zhí)行完畢后產生的結果。

使用線程池中線程對象的步驟:

  • 創(chuàng)建線程池對象。
  • 創(chuàng)建Runnable接口子類對象。(task)
  • 提交Runnable接口子類對象。(take task)
  • 關閉線程池(一般不做)。

Runnable實現類代碼:

public class MyRunnable implements Runnable {
? ? @Override
? ? public void run() {
? ? ? ? System.out.println("我要一個教練");
? ? ? ? try {
? ? ? ? ? ? Thread.sleep(2000);
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? System.out.println("教練來了: " + Thread.currentThread().getName());
? ? ? ? System.out.println("教我游泳,交完后,教練回到了游泳池");
? ? }
}

public class ThreadPoolDemo {
? ? public static void main(String[] args) {
? ? ? ? // 創(chuàng)建線程池對象
? ? ? ? ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
? ? ? ? // 創(chuàng)建Runnable實例對象
? ? ? ? MyRunnable r = new MyRunnable();

? ? ? ? //自己創(chuàng)建線程對象的方式
? ? ? ? // Thread t = new Thread(r);
? ? ? ? // t.start(); ---> 調用MyRunnable中的run()

? ? ? ? // 從線程池中獲取線程對象,然后調用MyRunnable中的run()
? ? ? ? service.submit(r);
? ? ? ? // 再獲取個線程對象,調用MyRunnable中的run()
? ? ? ? service.submit(r);
? ? ? ? service.submit(r);
? ? ? ? // 注意:submit方法調用結束后,程序并不終止,是因為線程池控制了線程的關閉。
? ? ? ? // 將使用完的線程又歸還到了線程池中
? ? ? ? // 關閉線程池
? ? ? ? //service.shutdown();
? ? }
}

Callable測試代碼:

<T> Future<T> submit(Callable<T> task) : 獲取線程池中的某一個線程對象,并執(zhí)行.
Future : 表示計算的結果.

V get()   : 獲取計算完成的結果。

public class ThreadPoolDemo2 {
? ? public static void main(String[] args) throws Exception {
? ? ? ? // 創(chuàng)建線程池對象
? ? ? ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象

? ? ? ? // 創(chuàng)建Runnable實例對象
? ? ? ? Callable<Double> c = new Callable<Double>() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public Double call() throws Exception {
? ? ? ? ? ? ? ? return Math.random();
? ? ? ? ? ? }
? ? ? ? };

? ? ? ? // 從線程池中獲取線程對象,然后調用Callable中的call()
? ? ? ? Future<Double> f1 = service.submit(c);
? ? ? ? // Futur 調用get() 獲取運算結果
? ? ? ? System.out.println(f1.get());

? ? ? ? Future<Double> f2 = service.submit(c);
? ? ? ? System.out.println(f2.get());

? ? ? ? Future<Double> f3 = service.submit(c);
? ? ? ? System.out.println(f3.get());
? ? }
}

線程池的練習

public class Demo04 {
? ? public static void main(String[] args) throws ExecutionException, InterruptedException {
? ? ? ? ExecutorService pool = Executors.newFixedThreadPool(3);

? ? ? ? SumCallable sc = new SumCallable(100);
? ? ? ? Future<Integer> fu = pool.submit(sc);
? ? ? ? Integer integer = fu.get();
? ? ? ? System.out.println("結果: " + integer);
? ? ? ??
? ? ? ? SumCallable sc2 = new SumCallable(200);
? ? ? ? Future<Integer> fu2 = pool.submit(sc2);
? ? ? ? Integer integer2 = fu2.get();
? ? ? ? System.out.println("結果: " + integer2);

? ? ? ? pool.shutdown();
? ? }
}
public class SumCallable implements Callable<Integer> {
? ? private int n;

? ? public SumCallable(int n) {
? ? ? ? this.n = n;
? ? }

? ? @Override
? ? public Integer call() throws Exception {
? ? ? ? // 求1-n的和?
? ? ? ? int sum = 0;
? ? ? ? for (int i = 1; i <= n; i++) {
? ? ? ? ? ? sum += i;
? ? ? ? }
? ? ? ? return sum;
? ? }
}

到此這篇關于Java并發(fā)包線程池ThreadPoolExecutor的實現的文章就介紹到這了,更多相關Java并發(fā)包線程池ThreadPoolExecutor內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java自旋鎖的實現示例

    Java自旋鎖的實現示例

    自旋鎖是一種特殊的鎖,用于解決多線程同步問題,本文主要介紹了Java自旋鎖的實現示例,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Java?C++題解leetcode817鏈表組件示例

    Java?C++題解leetcode817鏈表組件示例

    這篇文章主要為大家介紹了Java?C++題解leetcode817鏈表組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Java編程實現基于TCP協(xié)議的Socket聊天室示例

    Java編程實現基于TCP協(xié)議的Socket聊天室示例

    這篇文章主要介紹了Java編程實現基于TCP協(xié)議的Socket聊天室,結合實例形式詳細分析了java基于TCP協(xié)議的Socket聊天室客戶端與服務器端相關實現與使用技巧,需要的朋友可以參考下
    2018-01-01
  • java遞歸算法的實例詳解

    java遞歸算法的實例詳解

    在本篇文章里小編給大家整理了關于java遞歸算法的實例內容,以及相關知識點總結,需要的朋友們可以學習下。
    2020-02-02
  • IntelliJ IDEA中查看文件內所有已聲明的方法(類似eclipse的outline)

    IntelliJ IDEA中查看文件內所有已聲明的方法(類似eclipse的outline)

    今天小編就為大家分享一篇關于IntelliJ IDEA中查看文件內所有已聲明的方法(類似eclipse的outline),小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • SpringBoot Admin2.0 集成Arthas的實現步驟

    SpringBoot Admin2.0 集成Arthas的實現步驟

    這篇文章主要介紹了SpringBoot Admin2.0 集成Arthas的實現步驟,幫助大家更好的理解和學習使用SpringBoot框架,感興趣的朋友可以了解下
    2021-04-04
  • IDEA創(chuàng)建springboot + mybatis項目全過程(步驟詳解)

    IDEA創(chuàng)建springboot + mybatis項目全過程(步驟詳解)

    這篇文章主要介紹了IDEA創(chuàng)建springboot + mybatis項目全過程及步驟詳解,本文通圖文實例代碼相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • java定時任務的實現方法

    java定時任務的實現方法

    java定時任務的實現方法,需要的朋友可以參考一下
    2013-03-03
  • SpringBoot詳細講解如何創(chuàng)建及刷新Spring容器bean

    SpringBoot詳細講解如何創(chuàng)建及刷新Spring容器bean

    前面看spring源碼時可以發(fā)現refresh()方法十分重要。在這個方法中會加載beanDefinition,同時創(chuàng)建bean對象。那么在springboot中有沒有使用這個refresh()方法呢
    2022-06-06
  • Flink狀態(tài)和容錯源碼解析

    Flink狀態(tài)和容錯源碼解析

    這篇文章主要為大家介紹了Flink狀態(tài)和容錯源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12

最新評論