導航:首頁 > 源碼編譯 > 線程池開發源碼

線程池開發源碼

發布時間:2022-08-02 06:45:25

java線程池怎麼實現

要想理解清楚java線程池實現原理,明白下面幾個問題就可以了:

(1):線程池存在哪些狀態,這些狀態之間是如何進行切換的呢?

(2):線程池的種類有哪些?

(3):創建線程池需要哪些參數,這些參數的具體含義是什麼?

(4):將任務添加到線程池之後運行流程?

(5):線程池是怎麼做到重用線程的呢?

(6):線程池的關閉

首先回答第一個問題:線程池存在哪些狀態;

查看ThreadPoolExecutor源碼便知曉:

[java]view plain

㈡ 什麼是java線程池

多線程是為了能夠讓計算機資源合理的分配,對於處理不同的任務創建不同的線程進行處理,但是計算機創建一個線程或者銷毀一個線程所花費的也是比較昂貴的,有時候需要同時處理的事情比較多,就需要我們頻繁的進行線程的創建和銷毀,這樣花費的時間也是比較多的。為了解決這一問題,我們就可以引用線程池的概念。
所謂線程池就是將線程集中管理起來,當需要線程的時候,可以從線程池中獲取空閑的線程,這樣可以減少線程的頻繁創建與銷毀,節省很大的時間和減少很多不必要的操作。
在java中提供了ThreadPoolExecutor類來進行線程的管理,這個類繼承於AbstractExecutorService,而AbstractExecutorService實現了ExecutorService介面,我們可以使用ThreadPoolExecutor來進行線程池的創建。
在ThreadPoolExecutor的構造方法中,有多個參數,可以配置不同的參數來進行優化。這個類的源碼構造方法為:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)其中每個參數代表的意義分別為
corePoolSize : 線程池中的核心線程數量,當線程池中當前的線程數小於這個配置的時候,如果有一個新的任務到來,即使線程池中還存在空閑狀態的線程,程序也會繼續創建一個新的線程放進線程池當中
maximumPoolSize: 線程池中的線程最大數量
keepAliveTime:當線程池中的線程數量大於配置的核心線程數量(corePoolSize)的時候,如果當前有空閑的線程,則當這個空閑線程可以存在的時間,如果在keepAliveTime這個時間點內沒有新的任務使用這個線程,那麼這個線程將會結束,核心線程不會結束,但是如果配置了allowCoreThreadTimeOut = true,則當空閑時間超過keepAliveTime之後,線程也會被結束調,默認allowCoreThreadTimeOut = false,即表示默認情況下,核心線程會一直存在於線程池當中。
unit : 空閑線程保持連接時間(keepAliveTime)的時間單位
workQueue:阻塞的任務隊列,用來保存等待需要執行的任務。
threadFactory :線程工廠,可以根據自己的需求去創建線程的對象,設置線程的名稱,優先順序等屬性信息。
handler:當線程池中存在的線程數超過設置的最大值之後,新的任務就會被拒絕,可以自己定義一個拒絕的策略,當新任務被拒絕之後,就會使用hander方法進行處理。
在java中也提供了Executors工具類,在這個工具類中提供了多個創建線程池的靜態方法,其中包含newCachedThreadPool、newFixedThreadPool、newScheledThreadPool、newSingleThreadExecutor等。但是他們每個方法都是創建了ThreadPoolExecutor對象,不同的是,每個對象的初始 參數值不一樣;

㈢ Java線程池中的核心線程是如何被重復利用的

Java線程池中的核心線程是如何被重復利用的?

引言

在Java開發中,經常需要創建線程去執行一些任務,實現起來也非常方便,但如果並發的線程數量很多,並且每個線程都是執行一個時間很短的任務就結束了,這樣頻繁創建線程就會大大降低系統的效率,因為頻繁創建線程和銷毀線程需要時間。此時,我們很自然會想到使用線程池來解決這個問題。

使用線程池的好處:

㈣ 線程池如何保證核心線程不被銷毀

Java線程池中的核心線程是如何被重復利用的?

引言

在Java開發中,經常需要創建線程去執行一些任務,實現起來也非常方便,但如果並發的線程數量很多,並且每個線程都是執行一個時間很短的任務就結束了,這樣頻繁創建線程就會大大降低系統的效率,因為頻繁創建線程和銷毀線程需要時間。此時,我們很自然會想到使用線程池來解決這個問題。

使用線程池的好處:

㈤ 哪裡有開源的C++線程池代碼

1: glib是使用廣泛的開源c庫,有線程池,可以參考。
2: boost的threadpool,也是開源的線程池實現,不過模板太多,源碼有點難以看懂

㈥ java 多線程怎麼深入

並發與並行

並行,表示兩個線程同時做事情。

並發,表示一會做這個事情,一會做另一個事情,存在著調度。單核 CPU 不可能存在並行(微觀上)。

image

以上就是原生線程池創建的核心原理。除了原生線程池之外並發包還提供了簡單的創建方式,上面也說了它們是對原生線程池的一種包裝,可以讓開發者簡單快捷的創建所需要的線程池。

Executors

newSingleThreadExecutor

創建一個線程的線程池,在這個線程池中始終只有一個線程存在。如果線程池中的線程因為異常問題退出,那麼會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。

newFixedThreadPool

創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那麼線程池會補充一個新線程。

newCachedThreadPool

可根據實際情況,調整線程數量的線程池,線程池中的線程數量不確定,如果有空閑線程會優先選擇空閑線程,如果沒有空閑線程並且此時有任務提交會創建新的線程。在正常開發中並不推薦這個線程池,因為在極端情況下,會因為 newCachedThreadPool 創建過多線程而耗盡 CPU 和內存資源。

newScheledThreadPool

此線程池可以指定固定數量的線程來周期性的去執行。比如通過 scheleAtFixedRate 或者 scheleWithFixedDelay 來指定周期時間。

PS:另外在寫定時任務時(如果不用 Quartz 框架),最好採用這種線程池來做,因為它可以保證裡面始終是存在活的線程的。

推薦使用 ThreadPoolExecutor 方式

在阿里的 Java 開發手冊時有一條是不推薦使用 Executors 去創建,而是推薦去使用 ThreadPoolExecutor 來創建線程池。

這樣做的目的主要原因是:使用 Executors 創建線程池不會傳入核心參數,而是採用的默認值,這樣的話我們往往會忽略掉裡面參數的含義,如果業務場景要求比較苛刻的話,存在資源耗盡的風險;另外採用 ThreadPoolExecutor 的方式可以讓我們更加清楚地了解線程池的運行規則,不管是面試還是對技術成長都有莫大的好處。

改了變數,其他線程可以立即知道。保證可見性的方法有以下幾種:

  • volatile

  • 加入 volatile 關鍵字的變數在進行匯編時會多出一個 lock 前綴指令,這個前綴指令相當於一個內存屏障,內存屏障可以保證內存操作的順序。當聲明為 volatile 的變數進行寫操作時,那麼這個變數需要將數據寫到主內存中。

    由於處理器會實現緩存一致性協議,所以寫到主內存後會導致其他處理器的緩存無效,也就是線程工作內存無效,需要從主內存中重新刷新數據。

    ㈦ java 線程池 工作隊列是如何工作的

    使用線程池的好處

    1、降低資源消耗

    可以重復利用已創建的線程降低線程創建和銷毀造成的消耗。

    2、提高響應速度

    當任務到達時,任務可以不需要等到線程創建就能立即執行。

    3、提高線程的可管理性

    線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控

    線程池的工作原理

    首先我們看下當一個新的任務提交到線程池之後,線程池是如何處理的

    1、線程池判斷核心線程池裡的線程是否都在執行任務。如果不是,則創建一個新的工作線程來執行任務。如果核心線程池裡的線程都在執行任務,則執行第二步。

    2、線程池判斷工作隊列是否已經滿。如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列里進行等待。如果工作隊列滿了,則執行第三步

    3、線程池判斷線程池的線程是否都處於工作狀態。如果沒有,則創建一個新的工作線程來執行任務。如果已經滿了,則交給飽和策略來處理這個任務

    線程池飽和策略

    這里提到了線程池的飽和策略,那我們就簡單介紹下有哪些飽和策略:

    AbortPolicy

    為Java線程池默認的阻塞策略,不執行此任務,而且直接拋出一個運行時異常,切記ThreadPoolExecutor.execute需要try catch,否則程序會直接退出。

    DiscardPolicy

    直接拋棄,任務不執行,空方法

    DiscardOldestPolicy

    從隊列裡面拋棄head的一個任務,並再次execute 此task。

    CallerRunsPolicy

    在調用execute的線程裡面執行此command,會阻塞入口

    用戶自定義拒絕策略(最常用)

    實現RejectedExecutionHandler,並自己定義策略模式

    下我們以ThreadPoolExecutor為例展示下線程池的工作流程圖

    3.jpg

    關鍵方法源碼分析

    我們看看核心方法添加到線程池方法execute的源碼如下:

    // //Executes the given task sometime in the future. The task //may execute in a new thread or in an existing pooled thread. // // If the task cannot be submitted for execution, either because this // executor has been shutdown or because its capacity has been reached, // the task is handled by the current {@code RejectedExecutionHandler}. // // @param command the task to execute // @throws RejectedExecutionException at discretion of // {@code RejectedExecutionHandler}, if the task // cannot be accepted for execution // @throws NullPointerException if {@code command} is null // public void execute(Runnable command) { if (command == null) throw new NullPointerException(); // // Proceed in 3 steps: // // 1. If fewer than corePoolSize threads are running, try to // start a new thread with the given command as its first // task. The call to addWorker atomically checks runState and // workerCount, and so prevents false alarms that would add // threads when it shouldn't, by returning false. // 翻譯如下: // 判斷當前的線程數是否小於corePoolSize如果是,使用入參任務通過addWord方法創建一個新的線程, // 如果能完成新線程創建exexute方法結束,成功提交任務 // 2. If a task can be successfully queued, then we still need // to double-check whether we should have added a thread // (because existing ones died since last checking) or that // the pool shut down since entry into this method. So we // recheck state and if necessary roll back the enqueuing if // stopped, or start a new thread if there are none. // 翻譯如下: // 在第一步沒有完成任務提交;狀態為運行並且能否成功加入任務到工作隊列後,再進行一次check,如果狀態 // 在任務加入隊列後變為了非運行(有可能是在執行到這里線程池shutdown了),非運行狀態下當然是需要 // reject;然後再判斷當前線程數是否為0(有可能這個時候線程數變為了0),如是,新增一個線程; // 3. If we cannot queue task, then we try to add a new // thread. If it fails, we know we are shut down or saturated // and so reject the task. // 翻譯如下: // 如果不能加入任務到工作隊列,將嘗試使用任務新增一個線程,如果失敗,則是線程池已經shutdown或者線程池 // 已經達到飽和狀態,所以reject這個他任務 // int c = ctl.get(); // 工作線程數小於核心線程數 if (workerCountOf(c) < corePoolSize) { // 直接啟動新線程,true表示會再次檢查workerCount是否小於corePoolSize if (addWorker(command, true)) return; c = ctl.get(); } // 如果工作線程數大於等於核心線程數 // 線程的的狀態未RUNNING並且隊列notfull if (isRunning(c) && workQueue.offer(command)) { // 再次檢查線程的運行狀態,如果不是RUNNING直接從隊列中移除 int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) // 移除成功,拒絕該非運行的任務 reject(command); else if (workerCountOf(recheck) == 0) // 防止了SHUTDOWN狀態下沒有活動線程了,但是隊列里還有任務沒執行這種特殊情況。 // 添加一個null任務是因為SHUTDOWN狀態下,線程池不再接受新任務 addWorker(null, false); } // 如果隊列滿了或者是非運行的任務都拒絕執行 else if (!addWorker(command, false)) reject(command); }

    ㈧ 幾種開源Java Web容器線程池的實現方法簡介

    其中Resin從V3.0後需要購買才能用於商業目的,而其他兩種則是純開源的。可以分別從他們的網站上下載最新的二進制包和源代碼。
    作為Web容器,需要承受較高的訪問量,能夠同時響應不同用戶的請求,能夠在惡劣環境下保持較高的穩定性和健壯性。在HTTP伺服器領域,ApacheHTTPD的效率是最高的,也是最為穩定的,但它只能處理靜態頁面的請求,如果需要支持動態頁面請求,則必須安裝相應的插件,比如mod_perl可以處理Perl腳本,mod_python可以處理Python腳本。
    上面介紹的三中Web容器,都是使用Java編寫的HTTP伺服器,當然他們都可以嵌到Apache中使用,也可以獨立使用。分析它們處理客戶請求的方法有助於了解Java多線程和線程池的實現方法,為設計強大的多線程伺服器打好基礎。
    Tomcat是使用最廣的Java Web容器,功能強大,可擴展性強。最新版本的Tomcat(5.5.17)為了提高響應速度和效率,使用了Apache Portable Runtime(APR)作為最底層,使用了APR中包含Socket、緩沖池等多種技術,性能也提高了。APR也是Apache HTTPD的最底層。可想而知,同屬於ASF(Apache Software Foundation)中的成員,互補互用的情況還是很多的,雖然使用了不同的開發語言。
    Tomcat 的線程池位於tomcat-util.jar文件中,包含了兩種線程池方案。方案一:使用APR的Pool技術,使用了JNI;方案二:使用Java實現的ThreadPool。這里介紹的是第二種。如果想了解APR的Pool技術,可以查看APR的源代碼。
    ThreadPool默認創建了5個線程,保存在一個200維的線程數組中,創建時就啟動了這些線程,當然在沒有請求時,它們都處理等待狀態(其實就是一個while循環,不停的等待notify)。如果有請求時,空閑線程會被喚醒執行用戶的請求。
    具體的請求過程是:服務啟動時,創建一個一維線程數組(maxThread=200個),並創建空閑線程(minSpareThreads=5個)隨時等待用戶請求。當有用戶請求時,調用 threadpool.runIt(ThreadPoolRunnable)方法,將一個需要執行的實例傳給ThreadPool中。其中用戶需要執行的實例必須實現ThreadPoolRunnable介面。 ThreadPool首先查找空閑的線程,如果有則用它運行要執行ThreadPoolRunnable;如果沒有空閑線程並且沒有超過 maxThreads,就一次性創建minSpareThreads個空閑線程;如果已經超過了maxThreads了,就等待空閑線程了。總之,要找到空閑的線程,以便用它執行實例。找到後,將該線程從線程數組中移走。接著喚醒已經找到的空閑線程,用它運行執行實例(ThreadPoolRunnable)。運行完ThreadPoolRunnable後,就將該線程重新放到線程數組中,作為空閑線程供後續使用。
    由此可以看出,Tomcat的線程池實現是比較簡單的,ThreadPool.java也只有840行代碼。用一個一維數組保存空閑的線程,每次以一個較小步伐(5個)創建空閑線程並放到線程池中。使用時從數組中移走空閑的線程,用完後,再歸還給線程池。

    ㈨ 【Java基礎】線程池的原理是什麼

    什麼是線程池?

    總歸為:池化技術 ---》資料庫連接池 緩存架構 緩存池 線程池 內存池,連接池,這種思想演變成緩存架構技術---> JDK設計思想有千絲萬縷的聯系

    首先我們從最核心的ThreadPoolExecutor類中的方法講起,然後再講述它的實現原理,接著給出了它的使用示例,最後討論了一下如何合理配置線程池的大小。

    Java 中的 ThreadPoolExecutor 類

    java.uitl.concurrent.ThreadPoolExecutor 類是線程池中最核心的一個類,因此如果要透徹地了解Java 中的線程池,必須先了解這個類。下面我們來看一下 ThreadPoolExecutor 類的具體實現源碼。

    在 ThreadPoolExecutor 類中提供了四個構造方法:

    閱讀全文

    與線程池開發源碼相關的資料

    熱點內容
    加密系統能錄屏嗎 瀏覽:190
    安卓淘寶點進去跳鏈接如何關閉 瀏覽:786
    u盤加密了手機讀取不了 瀏覽:947
    oracle11g啟動命令 瀏覽:931
    怎麼把視頻傳到自己的文件夾 瀏覽:700
    福州電動車在哪個app上搖號 瀏覽:818
    禮書PDF 瀏覽:667
    什麼app看本子 瀏覽:394
    如何學好編譯語言 瀏覽:591
    平面編程和切削 瀏覽:704
    phpemoji表情符號 瀏覽:778
    IBM雲平台shor演算法 瀏覽:577
    程序員當乙方 瀏覽:519
    php商城設計與實現的 瀏覽:305
    php自動列印 瀏覽:469
    哪個app多年輕人 瀏覽:902
    租的伺服器如何重裝 瀏覽:937
    乾眼症程序員 瀏覽:239
    樂動達人安卓版有什麼游戲 瀏覽:484
    c523壓縮比 瀏覽:544