最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

10分鐘帶你徒手寫個Java線程池

 更新時間:2023年04月20日 08:43:56   作者:冰?河  
我們自己手動實現(xiàn)的線程池要比Java自身的線程池簡單的多,我們?nèi)サ袅烁鞣N復(fù)雜的處理方式,只保留了最核心的原理,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

Java線程池核心原理

看過Java線程池源碼的小伙伴都知道,在Java線程池中最核心的類就是ThreadPoolExecutor,而在ThreadPoolExecutor類中最核心的構(gòu)造方法就是帶有7個參數(shù)的構(gòu)造方法,如下所示。

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

各參數(shù)的含義如下所示。

  • corePoolSize:線程池中的常駐核心線程數(shù)。
  • maximumPoolSize:線程池能夠容納同時執(zhí)行的最大線程數(shù),此值大于等于1。
  • keepAliveTime:多余的空閑線程存活時間,當(dāng)空間時間達到keepAliveTime值時,多余的線程會被銷毀直到只剩下corePoolSize個線程為止。
  • unit:keepAliveTime的單位。
  • workQueue:任務(wù)隊列,被提交但尚未被執(zhí)行的任務(wù)。
  • threadFactory:表示生成線程池中工作線程的線程工廠,用戶創(chuàng)建新線程,一般用默認(rèn)即可。
  • handler:拒絕策略,表示當(dāng)線程隊列滿了并且工作線程大于等于線程池的最大顯示數(shù)(maxnumPoolSize)時,如何來拒絕請求執(zhí)行的runnable的策略。

并且Java的線程池是通過 生產(chǎn)者-消費者模式 實現(xiàn)的,線程池的使用方是生產(chǎn)者,而線程池本身就是消費者。

Java線程池的核心工作流程如下圖所示。

手?jǐn)]Java線程池

我們自己手動實現(xiàn)的線程池要比Java自身的線程池簡單的多,我們?nèi)サ袅烁鞣N復(fù)雜的處理方式,只保留了最核心的原理:線程池的使用者向任務(wù)隊列中添加任務(wù),而線程池本身從任務(wù)隊列中消費任務(wù)并執(zhí)行任務(wù)。

只要理解了這個核心原理,接下來的代碼就簡單多了。在實現(xiàn)這個簡單的線程池時,我們可以將整個實現(xiàn)過程進行拆解。拆解后的實現(xiàn)流程為:定義核心字段、創(chuàng)建內(nèi)部類WorkThread、創(chuàng)建ThreadPool類的構(gòu)造方法和創(chuàng)建執(zhí)行任務(wù)的方法。

定義核心字段

首先,我們創(chuàng)建一個名稱為ThreadPool的Java類,并在這個類中定義如下核心字段。

  • DEFAULT_WORKQUEUE_SIZE:靜態(tài)常量,表示默認(rèn)的阻塞隊列大小。
  • workQueue:模擬實際的線程池使用阻塞隊列來實現(xiàn)生產(chǎn)者-消費者模式。
  • workThreads:模擬實際的線程池使用List集合保存線程池內(nèi)部的工作線程。

核心代碼如下所示。

//默認(rèn)阻塞隊列大小
private static final int DEFAULT_WORKQUEUE_SIZE = 5;

//模擬實際的線程池使用阻塞隊列來實現(xiàn)生產(chǎn)者-消費者模式
private BlockingQueue<Runnable> workQueue;

//模擬實際的線程池使用List集合保存線程池內(nèi)部的工作線程
private List<WorkThread> workThreads = new ArrayList<WorkThread>();

創(chuàng)建內(nèi)部類WordThread

在ThreadPool類中創(chuàng)建一個內(nèi)部類WorkThread,模擬線程池中的工作線程。主要的作用就是消費workQueue中的任務(wù),并執(zhí)行任務(wù)。由于工作線程需要不斷從workQueue中獲取任務(wù),所以,這里使用了while(true)循環(huán)不斷嘗試消費隊列中的任務(wù)。

核心代碼如下所示。

//內(nèi)部類WorkThread,模擬線程池中的工作線程
//主要的作用就是消費workQueue中的任務(wù),并執(zhí)行
//由于工作線程需要不斷從workQueue中獲取任務(wù),使用了while(true)循環(huán)不斷嘗試消費隊列中的任務(wù)
class WorkThread extends Thread{
    @Override
    public void run() {
        //不斷循環(huán)獲取隊列中的任務(wù)
        while (true){
            //當(dāng)沒有任務(wù)時,會阻塞
            try {
                Runnable workTask = workQueue.take();
                workTask.run();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

創(chuàng)建ThreadPool類的構(gòu)造方法

這里,我們?yōu)門hreadPool類創(chuàng)建兩個構(gòu)造方法,一個構(gòu)造方法中傳入線程池的容量大小和阻塞隊列,另一個構(gòu)造方法中只傳入線程池的容量大小。

核心代碼如下所示。

//在ThreadPool的構(gòu)造方法中傳入線程池的大小和阻塞隊列
public ThreadPool(int poolSize, BlockingQueue<Runnable> workQueue){
    this.workQueue = workQueue;
    //創(chuàng)建poolSize個工作線程并將其加入到workThreads集合中
    IntStream.range(0, poolSize).forEach((i) -> {
        WorkThread workThread = new WorkThread();
        workThread.start();
        workThreads.add(workThread);
    });
}

//在ThreadPool的構(gòu)造方法中傳入線程池的大小
public ThreadPool(int poolSize){
    this(poolSize, new LinkedBlockingQueue<>(DEFAULT_WORKQUEUE_SIZE));
}

創(chuàng)建執(zhí)行任務(wù)的方法

在ThreadPool類中創(chuàng)建執(zhí)行任務(wù)的方法execute(),execute()方法的實現(xiàn)比較簡單,就是將方法接收到的Runnable任務(wù)加入到workQueue隊列中。

核心代碼如下所示。

//通過線程池執(zhí)行任務(wù)
public void execute(Runnable task){
    try {
        workQueue.put(task);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

完整源碼

這里,我們給出手動實現(xiàn)的ThreadPool線程池的完整源代碼,如下所示。

package io.binghe.thread.pool;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.IntStream;

/**
 * @author binghe
 * @version 1.0.0
 * @description 自定義線程池
 */
public class ThreadPool {

    //默認(rèn)阻塞隊列大小
    private static final int DEFAULT_WORKQUEUE_SIZE = 5;

    //模擬實際的線程池使用阻塞隊列來實現(xiàn)生產(chǎn)者-消費者模式
    private BlockingQueue<Runnable> workQueue;

    //模擬實際的線程池使用List集合保存線程池內(nèi)部的工作線程
    private List<WorkThread> workThreads = new ArrayList<WorkThread>();

    //在ThreadPool的構(gòu)造方法中傳入線程池的大小和阻塞隊列
    public ThreadPool(int poolSize, BlockingQueue<Runnable> workQueue){
        this.workQueue = workQueue;
        //創(chuàng)建poolSize個工作線程并將其加入到workThreads集合中
        IntStream.range(0, poolSize).forEach((i) -> {
            WorkThread workThread = new WorkThread();
            workThread.start();
            workThreads.add(workThread);
        });
    }

    //在ThreadPool的構(gòu)造方法中傳入線程池的大小
    public ThreadPool(int poolSize){
        this(poolSize, new LinkedBlockingQueue<>(DEFAULT_WORKQUEUE_SIZE));
    }

 //通過線程池執(zhí)行任務(wù)
    public void execute(Runnable task){
        try {
            workQueue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //內(nèi)部類WorkThread,模擬線程池中的工作線程
    //主要的作用就是消費workQueue中的任務(wù),并執(zhí)行
    //由于工作線程需要不斷從workQueue中獲取任務(wù),使用了while(true)循環(huán)不斷嘗試消費隊列中的任務(wù)
    class WorkThread extends Thread{
        @Override
        public void run() {
            //不斷循環(huán)獲取隊列中的任務(wù)
            while (true){
                //當(dāng)沒有任務(wù)時,會阻塞
                try {
                    Runnable workTask = workQueue.take();
                    workTask.run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

沒錯,我們僅僅用了幾十行Java代碼就實現(xiàn)了一個極簡版的Java線程池,沒錯,這個極簡版的Java線程池的代碼卻體現(xiàn)了Java線程池的核心原理。

接下來,我們測試下這個極簡版的Java線程池。

編寫測試程序

測試程序也比較簡單,就是通過在main()方法中調(diào)用ThreadPool類的構(gòu)造方法,傳入線程池的大小,創(chuàng)建一個ThreadPool類的實例,然后循環(huán)10次調(diào)用ThreadPool類的execute()方法,向線程池中提交的任務(wù)為:打印當(dāng)前線程的名稱--->> Hello ThreadPool。

整體測試代碼如下所示。

package io.binghe.thread.pool.test;

import io.binghe.thread.pool.ThreadPool;

import java.util.stream.IntStream;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試自定義線程池
 */
public class ThreadPoolTest {

    public static void main(String[] args){
        ThreadPool threadPool = new ThreadPool(10);
        IntStream.range(0, 10).forEach((i) -> {
            threadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "--->> Hello ThreadPool");
            });
        });
    }
}

接下來,運行ThreadPoolTest類的main()方法,會輸出如下信息。

Thread-0--->> Hello ThreadPool
Thread-9--->> Hello ThreadPool
Thread-5--->> Hello ThreadPool
Thread-8--->> Hello ThreadPool
Thread-4--->> Hello ThreadPool
Thread-1--->> Hello ThreadPool
Thread-2--->> Hello ThreadPool
Thread-5--->> Hello ThreadPool
Thread-9--->> Hello ThreadPool
Thread-0--->> Hello ThreadPool

至此,我們自定義的Java線程池就開發(fā)完成了。

總結(jié)

線程池的核心原理其實并不復(fù)雜,只要我們耐心的分析,深入其源碼理解線程池的核心本質(zhì),你就會發(fā)現(xiàn)線程池的設(shè)計原來是如此的優(yōu)雅。希望通過這個手寫線程池的小例子,能夠讓你更好的理解線程池的核心原理。

以上就是10分鐘帶你徒手寫個Java線程池的詳細(xì)內(nèi)容,更多關(guān)于Java線程池的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot JPA實現(xiàn)查詢多值

    SpringBoot JPA實現(xiàn)查詢多值

    這篇文章主要為大家詳細(xì)介紹了SpringBoot JPA實現(xiàn)查詢多值,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運行 java 代碼

    MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運行 java 代碼

    這篇文章主要介紹了MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運行 java 代碼,需要的朋友可以參考下
    2014-10-10
  • java synchronized加載加鎖-線程可重入詳解及實例代碼

    java synchronized加載加鎖-線程可重入詳解及實例代碼

    這篇文章主要介紹了java synchronized加載加鎖-線程可重入詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Kotlin this詳解及實例

    Kotlin this詳解及實例

    這篇文章主要介紹了Kotlin this詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Java 并發(fā)編程的可見性、有序性和原子性

    Java 并發(fā)編程的可見性、有序性和原子性

    這篇文章主要介紹了Java 并發(fā)編程的可見性、有序性和原子性的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java并發(fā)編程,感興趣的朋友可以了解下。
    2020-11-11
  • 解析Neatbeans(常見錯誤) build-impl.xml:305: Compile failed

    解析Neatbeans(常見錯誤) build-impl.xml:305: Compile failed

    本篇文章是對Neatbeans(常見錯誤) build-impl.xml:305: Compile failed的解決方法進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • SpringBoot參數(shù)校驗示例詳解

    SpringBoot參數(shù)校驗示例詳解

    SpringBoot自帶了validation工具可以從后端對前端傳來的參數(shù)進行校驗,本文給大家介紹SpringBoot參數(shù)校驗及用法,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • Spring Boot加載配置文件的完整步驟

    Spring Boot加載配置文件的完整步驟

    這篇文章主要給大家介紹了關(guān)于Spring Boot加載配置文件的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • JavaSE一維數(shù)組和二維數(shù)組用法詳解

    JavaSE一維數(shù)組和二維數(shù)組用法詳解

    數(shù)組存儲同一種數(shù)據(jù)類型多個元素的集合,既可以存儲基本數(shù)據(jù)類型,也可以存儲引用數(shù)據(jù)類型,這篇文章主要給大家介紹了關(guān)于JavaSE一維數(shù)組和二維數(shù)組用法的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • java程序員必會的遠程debug教程

    java程序員必會的遠程debug教程

    這篇文章主要為大家介紹了java程序員必會的遠程debug教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08

最新評論

宁远县| 伽师县| 德兴市| 赫章县| 蒲城县| 灵山县| 宝丰县| 永泰县| 城口县| 丹阳市| 连云港市| 怀化市| 赫章县| 肇庆市| 额敏县| 阳山县| 广河县| 西盟| 汶上县| 普安县| 周口市| 富民县| 虹口区| 渭源县| 天柱县| 内黄县| 华池县| 伊金霍洛旗| 武宁县| 芦溪县| 久治县| 大英县| 石屏县| 安达市| 扶绥县| 阿拉善右旗| 甘泉县| 施甸县| 抚顺县| 宜兰县| 威海市|