導航:首頁 > 編程語言 > java線程池源碼

java線程池源碼

發布時間:2022-04-22 08:37:39

A. 什麼是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對象,不同的是,每個對象的初始 參數值不一樣;

B. JAVA線程池shutdown和shutdownNow的區別

shutDown()當線程池調用該方法時,線程池的狀態則立刻變成SHUTDOWN狀態。此時,則不能再往線程池中添加任何任務,否則將會拋出RejectedExecutionException異常。但是,此時線程池不會立刻退出,直到添加到線程池中的任務都已經處理完成,才會退出。shutdownNow()根據JDK文檔描述,大致意思是:執行該方法,線程池的狀態立刻變成STOP狀態,並試圖停止所有正在執行的線程,不再處理還在池隊列中等待的任務,當然,它會返回那些未執行的任務。它試圖終止線程的方法是通過調用Thread.interrupt()方法來實現的,但是大家知道,這種方法的作用有限,如果線程中沒有sleep、wait、Condition、定時鎖等應用,interrupt()方法是無法中斷當前的線程的。所以,ShutdownNow()並不代表線程池就一定立即就能退出,它可能必須要等待所有正在執行的任務都執行完成了才能退出。上面對shutDown()以及shutDownNow()作了一個簡單的、理論上的分析。如果想知道why,則需要親自打開JDK源碼,分析分析。想要分析shutDown()以及shutDownNow()源碼,我建議首先要對ThreadPoolExecutor有個大概了解。因為關閉線程池的所有方法邏輯都在ThreadPoolExecutor中處理的。如果你真的想知道為什麼,建議看一下我以前寫的一篇對ThreadPoolExecutor源碼分析的博文,我想這對你比較透徹的了解shutDown()和shutDownNow()的區別以及java線程池原理有很大的幫助。廢話少說,要查看源碼,首先進入ThreadPoolExecutor的shutDown()方法:Java代碼收藏代碼publicvoidshutdown(){SecurityManagersecurity=System.getSecurityManager();if(security!=null)security.checkPermission(shutdownPerm);finalReentrantLockmainLock=this.mainLock;mainLock.lock();try{if(security!=null){//(Workerw:workers)security.checkAccess(w.thread);}intstate=runState;if(state

C. 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); }

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

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

引言

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

使用線程池的好處:

E. java線程池怎麼實現

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

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

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

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

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

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

(6):線程池的關閉

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

查看ThreadPoolExecutor源碼便知曉:

[java]view plain

F. 什麼樣的java線程池可以使用處理數據從插座嗎

Java通過Executors提供四種線程池,分別為:
newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
newFixedThreadPool 創建一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。
newScheledThreadPool 創建一個定長線程池,支持定時及周期性任務執行。
newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。

(1) newCachedThreadPool
創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。示例代碼如下:

Java代碼

選擇我們運行的程序:

監控運行狀態

G. java線程池有哪些

一:newCachedThreadPool
(1)緩存型池子,先查看池中有沒有以前建立的線程,如果有,就reuse,如果沒有,就建立一個新的線程加入池中;
(2)緩存型池子,通常用於執行一些生存周期很短的非同步型任務;因此一些面向連接的daemon型server中用得不多;
(3)能reuse的線程,必須是timeout IDLE內的池中線程,預設timeout是60s,超過這個IDLE時長,線程實例將被終止及移出池。
(4)注意,放入CachedThreadPool的線程不必擔心其結束,超過TIMEOUT不活動,其會自動被終止

二:newFixedThreadPool
(1)newFixedThreadPool與cacheThreadPool差不多,也是能reuse就用,但不能隨時建新的線程
(2)其獨特之處:任意時間點,最多隻能有固定數目的活動線程存在,此時如果有新的線程要建立,只能放在另外的隊列中等待,直到當前的線程中某個線程終止直接被移出池子
(3)和cacheThreadPool不同,FixedThreadPool沒有IDLE機制(可能也有,但既然文檔沒提,肯定非常長,類似依賴上層的TCP或UDP IDLE機制之類的),所以FixedThreadPool多數針對一些很穩定很固定的正規並發線程,多用於伺服器
(4)從方法的源代碼看,cache池和fixed 池調用的是同一個底層池,只不過參數不同:
fixed池線程數固定,並且是0秒IDLE(無IDLE)
cache池線程數支持0-Integer.MAX_VALUE(顯然完全沒考慮主機的資源承受能力),60秒IDLE

三:ScheledThreadPool
(1)調度型線程池
(2)這個池子里的線程可以按schele依次delay執行,或周期執行
四:SingleThreadExecutor
(1)單例線程,任意時間池中只能有一個線程
(2)用的是和cache池和fixed池相同的底層池,但線程數目是1-1,0秒IDLE(無IDLE)

H. Java的線程池,如何設定保留的最小線程數和固定的隊列容量

創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。在任意點,在大多數 nThreads 線程會處於處理任務的活動狀態。如果在所有線程處於活動狀態時提交附加任務,則在有可用線程之前,附加任務將在隊列中等待。如果在關閉前的執行期間由於失敗而導致任何線程終止,那麼一個新線程將代替它執行後續的任務(如果需要)。在某個線程被顯式地關閉之前,池中的線程將一直存在。

看代碼:
Java代碼 收藏代碼
package test;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ExecutorTest {
public static void main(String args[]) {
Random random = new Random();
//產生一個 ExecutorService 對象,這個對象帶有一個大小為 poolSize 的線程池,若任務數量大於 poolSize ,任務會被放在一個 queue 里順序執行。
ExecutorService executor = Executors.newFixedThreadPool(3);
// 判斷可是線程池可以結束
int waitTime = 500;
for (int i = 0; i < 10; i++) {
String name = "線程 " + i;
int time = random.nextInt(1000);
waitTime += time;
Runnable runner = new ExecutorThread(name, time);
System.out.println("增加: " + name + " / " + time);
executor.execute(runner);
}
try {
Thread.sleep(waitTime);
executor.shutdown();
executor.awaitTermination(waitTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
}
}
}

class ExecutorThread implements Runnable {
private final String name;
private final int delay;
public ExecutorThread(String name, int delay) {
this.name = name;
this.delay = delay;
}
public void run() {
System.out.println("啟動: " + name);
try {
Thread.sleep(delay);
} catch (InterruptedException ignored) {
}
System.out.println("完成: " + name);
}
}

I. 尋Java 線程池demo

public class ThreadPoolMain extends Object {

public static Runnable makeRunnable(final String name, final long firstDelay) {

return new Runnable() {
public void run() {
try {
System.out.println(name + ": starting up");
Thread.sleep(firstDelay);
System.out.println(name + ": doing some stuff");
Thread.sleep(2000);
System.out.println(name + ": leaving");
} catch (InterruptedException ix) {
System.out.println(name + ": got interrupted!");
return;
} catch (Exception x) {
x.printStackTrace();
}
}

public String toString() {
return name;
}
};
}

public static void main(String[] args) {
try {
ThreadPool pool = new ThreadPool(3);

Runnable ra = makeRunnable("RA", 3000);
pool.execute(ra);

Runnable rb = makeRunnable("RB", 1000);
pool.execute(rb);

Runnable rc = makeRunnable("RC", 2000);
pool.execute(rc);

Runnable rd = makeRunnable("RD", 60000);
pool.execute(rd);

Runnable re = makeRunnable("RE", 1000);
pool.execute(re);

pool.stopRequestIdleWorkers();
Thread.sleep(2000);
pool.stopRequestIdleWorkers();

Thread.sleep(5000);
pool.stopRequestAllWorkers();
} catch (InterruptedException ix) {
ix.printStackTrace();
}
}
}

閱讀全文

與java線程池源碼相關的資料

熱點內容
linux打包命令targz 瀏覽:996
抖音app是哪個 瀏覽:407
蘋果app怎麼上架 瀏覽:255
NA伺服器地址 瀏覽:427
我的世界如何初始化伺服器 瀏覽:97
哪個手機app天氣預報最准 瀏覽:752
怎樣把視頻壓縮至25m 瀏覽:570
vivox27文件夾怎麼改變 瀏覽:727
新手玩狼人殺用什麼app 瀏覽:615
pdf在線查看 瀏覽:954
安卓tv90如何關閉後台 瀏覽:683
php讀取word亂碼 瀏覽:755
minicom源碼 瀏覽:1001
海爾冷櫃壓縮機 瀏覽:416
聯通伺服器如何調試信號 瀏覽:136
stata新命令 瀏覽:941
單調棧演算法python 瀏覽:606
微信解壓游戲怎麼下載 瀏覽:962
忍三伺服器不同如何登上賬號 瀏覽:822
php求積 瀏覽:297