一、簡(jiǎn)介
線程池類為 java.util.concurrent.threadpoolexecutor
,常用構(gòu)造方法為:
1
2
3
4
|
threadpoolexecutor( int corepoolsize, int maximumpoolsize, long keepalivetime, timeunit unit, blockingqueue workqueue, rejectedexecutionhandler handler) |
- corepoolsize: 線程池維護(hù)線程的最少數(shù)量
- maximumpoolsize:線程池維護(hù)線程的最大數(shù)量
- keepalivetime: 線程池維護(hù)線程所允許的空閑時(shí)間
- unit: 線程池維護(hù)線程所允許的空閑時(shí)間的單位
- workqueue: 線程池所使用的緩沖隊(duì)列
- handler: 線程池對(duì)拒絕任務(wù)的處理策略
一個(gè)任務(wù)通過 execute(runnable)
方法被添加到線程池,任務(wù)就是一個(gè) runnable類型的對(duì)象,任務(wù)的執(zhí)行方法就是 runnable類型對(duì)象的run()方法。
當(dāng)一個(gè)任務(wù)通過execute(runnable)方法欲添加到線程池時(shí):
- 如果此時(shí)線程池中的數(shù)量小于corepoolsize,即使線程池中的線程都處于空閑狀態(tài),也要?jiǎng)?chuàng)建新的線程來處理被添加的任務(wù)。
- 如果此時(shí)線程池中的數(shù)量等于 corepoolsize,但是緩沖隊(duì)列 workqueue未滿,那么任務(wù)被放入緩沖隊(duì)列。
- 如果此時(shí)線程池中的數(shù)量大于corepoolsize,緩沖隊(duì)列workqueue滿,并且線程池中的數(shù)量小于maximumpoolsize,建新的線程來處理被添加的任務(wù)。
- 如果此時(shí)線程池中的數(shù)量大于corepoolsize,緩沖隊(duì)列workqueue滿,并且線程池中的數(shù)量等于maximumpoolsize,那么通過 handler所指定的策略來處理此任務(wù)。
也就是:處理任務(wù)的優(yōu)先級(jí)為:
核心線程corepoolsize、任務(wù)隊(duì)列workqueue、最大線程maximumpoolsize,如果三者都滿了,使用handler處理被拒絕的任務(wù)。
當(dāng)線程池中的線程數(shù)量大于 corepoolsize時(shí),如果某線程空閑時(shí)間超過keepalivetime,線程將被終止。這樣,線程池可以動(dòng)態(tài)的調(diào)整池中的線程數(shù)。
unit可選的參數(shù)為java.util.concurrent.timeunit中的幾個(gè)靜態(tài)屬性:
nanoseconds、microseconds、milliseconds、seconds。
workqueue我常用的是:java.util.concurrent.arrayblockingqueue
handler有四個(gè)選擇:
- threadpoolexecutor.abortpolicy() 拋出java.util.concurrent.rejectedexecutionexception異常
- threadpoolexecutor.callerrunspolicy() 重試添加當(dāng)前的任務(wù),他會(huì)自動(dòng)重復(fù)調(diào)用execute()方法
- threadpoolexecutor.discardoldestpolicy() 拋棄舊的任務(wù)
- threadpoolexecutor.discardpolicy() 拋棄當(dāng)前的任務(wù)
二、一般用法舉例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
package demo; import java.io.serializable; import java.util.concurrent.arrayblockingqueue; import java.util.concurrent.threadpoolexecutor; import java.util.concurrent.timeunit; public class testthreadpool2 { private static int producetasksleeptime = 2 ; private static int producetaskmaxnumber = 10 ; public static void main(string[] args) { // 構(gòu)造一個(gè)線程池 threadpoolexecutor threadpool = new threadpoolexecutor( 2 , 4 , 3 , timeunit.seconds, new arrayblockingqueue<runnable>( 3 ), new threadpoolexecutor.discardoldestpolicy()); for ( int i = 1 ; i <= producetaskmaxnumber; i++) { try { // 產(chǎn)生一個(gè)任務(wù),并將其加入到線程池 string task = "task@ " + i; system.out.println( "put " + task); threadpool.execute( new threadpooltask(task)); // 便于觀察,等待一段時(shí)間 thread.sleep(producetasksleeptime); } catch (exception e) { e.printstacktrace(); } } } } /** * 線程池執(zhí)行的任務(wù) */ class threadpooltask implements runnable, serializable { private static final long serialversionuid = 0 ; private static int consumetasksleeptime = 2000 ; // 保存任務(wù)所需要的數(shù)據(jù) private object threadpooltaskdata; threadpooltask(object tasks) { this .threadpooltaskdata = tasks; } public void run() { // 處理一個(gè)任務(wù),這里的處理方式太簡(jiǎn)單了,僅僅是一個(gè)打印語句 system.out.println(thread.currentthread().getname()); system.out.println( "start .." + threadpooltaskdata); try { // //便于觀察,等待一段時(shí)間 thread.sleep(consumetasksleeptime); } catch (exception e) { e.printstacktrace(); } threadpooltaskdata = null ; } public object gettask() { return this .threadpooltaskdata; } } |
說明:
1、在這段程序中,一個(gè)任務(wù)就是一個(gè)runnable類型的對(duì)象,也就是一個(gè)threadpooltask類型的對(duì)象。
2、一般來說任務(wù)除了處理方式外,還需要處理的數(shù)據(jù),處理的數(shù)據(jù)通過構(gòu)造方法傳給任務(wù)。
3、在這段程序中,main()方法相當(dāng)于一個(gè)殘忍的領(lǐng)導(dǎo),他派發(fā)出許多任務(wù),丟給一個(gè)叫 threadpool的任勞任怨的小組來做。
這個(gè)小組里面隊(duì)員至少有兩個(gè),如果他們兩個(gè)忙不過來,任務(wù)就被放到任務(wù)列表里面。
如果積壓的任務(wù)過多,多到任務(wù)列表都裝不下(超過3個(gè))的時(shí)候,就雇傭新的隊(duì)員來幫忙。但是基于成本的考慮,不能雇傭太多的隊(duì)員,至多只能雇傭 4個(gè)。
如果四個(gè)隊(duì)員都在忙時(shí),再有新的任務(wù),這個(gè)小組就處理不了了,任務(wù)就會(huì)被通過一種策略來處理,我們的處理方式是不停的派發(fā),直到接受這個(gè)任務(wù)為止(更殘忍!呵呵)。
因?yàn)殛?duì)員工作是需要成本的,如果工作很閑,閑到 3seconds都沒有新的任務(wù)了,那么有的隊(duì)員就會(huì)被解雇了,但是,為了小組的正常運(yùn)轉(zhuǎn),即使工作再閑,小組的隊(duì)員也不能少于兩個(gè)。
4、通過調(diào)整 producetasksleeptime和 consumetasksleeptime的大小來實(shí)現(xiàn)對(duì)派發(fā)任務(wù)和處理任務(wù)的速度的控制,改變這兩個(gè)值就可以觀察不同速率下程序的工作情況。
5、通過調(diào)整4中所指的數(shù)據(jù),再加上調(diào)整任務(wù)丟棄策略,換上其他三種策略,就可以看出不同策略下的不同處理方式。
6、對(duì)于其他的使用方法,參看jdk的幫助,很容易理解和使用。
另一個(gè)例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
package demo; import java.util.queue; import java.util.concurrent.arrayblockingqueue; import java.util.concurrent.threadpoolexecutor; import java.util.concurrent.timeunit; public class threadpoolexecutortest { private static int queuedeep = 4 ; public void createthreadpool() { /* * 創(chuàng)建線程池,最小線程數(shù)為2,最大線程數(shù)為4,線程池維護(hù)線程的空閑時(shí)間為3秒, * 使用隊(duì)列深度為4的有界隊(duì)列,如果執(zhí)行程序尚未關(guān)閉,則位于工作隊(duì)列頭部的任務(wù)將被刪除, * 然后重試執(zhí)行程序(如果再次失敗,則重復(fù)此過程),里面已經(jīng)根據(jù)隊(duì)列深度對(duì)任務(wù)加載進(jìn)行了控制。 */ threadpoolexecutor tpe = new threadpoolexecutor( 2 , 4 , 3 , timeunit.seconds, new arrayblockingqueue<runnable>(queuedeep), new threadpoolexecutor.discardoldestpolicy()); // 向線程池中添加 10 個(gè)任務(wù) for ( int i = 0 ; i < 10 ; i++) { try { thread.sleep( 1 ); } catch (interruptedexception e) { e.printstacktrace(); } while (getqueuesize(tpe.getqueue()) >= queuedeep) { system.out.println( "隊(duì)列已滿,等3秒再添加任務(wù)" ); try { thread.sleep( 3000 ); } catch (interruptedexception e) { e.printstacktrace(); } } taskthreadpool ttp = new taskthreadpool(i); system.out.println( "put i:" + i); tpe.execute(ttp); } tpe.shutdown(); } private synchronized int getqueuesize(queue queue) { return queue.size(); } public static void main(string[] args) { threadpoolexecutortest test = new threadpoolexecutortest(); test.createthreadpool(); } class taskthreadpool implements runnable { private int index; public taskthreadpool( int index) { this .index = index; } public void run() { system.out.println(thread.currentthread() + " index:" + index); try { thread.sleep( 3000 ); } catch (interruptedexception e) { e.printstacktrace(); } } } } |
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)服務(wù)器之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
原文鏈接:https://blog.csdn.net/qq_26562641/article/details/55189875