什么原因使我們不得不使用線程池?
個(gè)人認(rèn)為主要原因是:短時(shí)間內(nèi)需要處理的任務(wù)數(shù)量很多
使用線程池的好處:
1.減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開(kāi)銷
2.如不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量線程而導(dǎo)致消耗完系統(tǒng)內(nèi)存
以下是Java自帶的幾種線程池:
1、newFixedThreadPool 創(chuàng)建一個(gè)指定工作線程數(shù)量的線程池。
每當(dāng)提交一個(gè)任務(wù)就創(chuàng)建一個(gè)工作線程,如果工作線程數(shù)量達(dá)到線程池初始的最大數(shù),則將提交的任務(wù)存入到池隊(duì)列中。
2、newCachedThreadPool 創(chuàng)建一個(gè)可緩存的線程池。
這種類型的線程池特點(diǎn)是:
1).工作線程的創(chuàng)建數(shù)量幾乎沒(méi)有限制(其實(shí)也有限制的,數(shù)目為Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。
2).如果長(zhǎng)時(shí)間沒(méi)有往線程池中提交任務(wù),即如果工作線程空閑了指定的時(shí)間(默認(rèn)為1分鐘),則該工作線程將自動(dòng)終止。終止后,如果你又提交了新的任務(wù),則線程池重新創(chuàng)建一個(gè)工作線程。
3、newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的Executor,即只創(chuàng)建唯一的工作者線程來(lái)執(zhí)行任務(wù),如果這個(gè)線程異常結(jié)束,會(huì)有另一個(gè)取代它,保證順序執(zhí)行(我覺(jué)得這點(diǎn)是它的特色)。
單工作線程最大的特點(diǎn)是可保證順序地執(zhí)行各個(gè)任務(wù),并且在任意給定的時(shí)間不會(huì)有多個(gè)線程是活動(dòng)的 。
4、newScheduleThreadPool 創(chuàng)建一個(gè)定長(zhǎng)的線程池,而且支持定時(shí)的以及周期性的任務(wù)執(zhí)行,類似于Timer。
總結(jié):
一.FixedThreadPool是一個(gè)典型且優(yōu)秀的線程池,它具有線程池提高程序效率和節(jié)省創(chuàng)建線程時(shí)所耗的開(kāi)銷的優(yōu)點(diǎn)。但在線程池空閑時(shí),即線程池中沒(méi)有可運(yùn)行任務(wù)時(shí),它不會(huì)釋放工作線程,還會(huì)占用一定的系統(tǒng)資源。
二.CachedThreadPool的特點(diǎn)就是在線程池空閑時(shí),即線程池中沒(méi)有可運(yùn)行任務(wù)時(shí),它會(huì)釋放工作線程,從而釋放工作線程所占用的資源。但是,但當(dāng)出現(xiàn)新任務(wù)時(shí),又要?jiǎng)?chuàng)建一新的工作線程,又要一定的系統(tǒng)開(kāi)銷。并且,在使用CachedThreadPool時(shí),一定要注意控制任務(wù)的數(shù)量,否則,由于大量線程同時(shí)運(yùn)行,很有會(huì)造成系統(tǒng)癱瘓。
Java線程池 ThreadPoolExecutor使用實(shí)例
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
package com.sondon.mayi.jpool; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class JPoolLearn { private static int produceTaskSleepTime = 3 ; private static int produceTaskMaxNumber = 20 ; public void testThreadPoolExecutor(){ /* * ThreadPoolExecutor( * int corePoolSize, //線程池維護(hù)線程的最少數(shù)量 * int maximumPoolSize, //線程池維護(hù)線程的最大數(shù)量 * long keepAliveTime, //線程池維護(hù)線程所允許的空閑時(shí)間 * TimeUnit unit, //線程池維護(hù)線程所允許的空閑時(shí)間的單位 * BlockingQueue<Runnable> workQueue, //線程池所使用的緩沖隊(duì)列 * RejectedExecutionHandler handler //線程池對(duì)拒絕任務(wù)的處理策略 ) */ ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.DiscardOldestPolicy() ); for (int i = 1; i <= produceTaskMaxNumber; i++) { try { // 產(chǎn)生一個(gè)任務(wù),并將其加入到線程池 String task = "task---" + i; threadPool.execute(new ThreadPoolTask(task)); System.out.println("activeCount :"+ threadPool.getActiveCount()); // 便于觀察,等待一段時(shí)間 Thread.sleep(produceTaskSleepTime); } catch (Exception e) { e.printStackTrace(); } } //查看當(dāng)前的線程池狀況 while(true){ try { Thread.sleep(3000); System.out.println("pool size :"+threadPool.getPoolSize());//線程池中線程數(shù)量 System.out.println("active count :"+threadPool.getActiveCount());//線程池中活動(dòng)的線程數(shù)量 } catch (InterruptedException e) { e.printStackTrace(); } } } /** * * @Author 蔡文鋒 * @Data_Time 2015年7月25日 下午4:06:28 * @Description { 測(cè)試不同線程池模式 } */ public void testNewCachedThreadPool(){ ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newCachedThreadPool(); // ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newFixedThreadPool(100); // ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newScheduledThreadPool(100); // ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newSingleThreadExecutor(); try { for (int i = 0; i < 100; i++) { // 產(chǎn)生一個(gè)任務(wù),并將其加入到線程池 String task = "task---" + i; threadPool.execute(new ThreadPoolTask(task)); System.out.println("activeCount :"); // 便于觀察,等待一段時(shí)間 Thread.sleep(produceTaskSleepTime); } } catch (InterruptedException e) { e.printStackTrace(); } //查看當(dāng)前的線程池狀況 while(true){ try { Thread.sleep(3000); System.out.println("pool size :"+threadPool.getPoolSize());//線程池中線程數(shù)量 System.out.println("active count :"+threadPool.getActiveCount());//線程池中活動(dòng)的線程數(shù)量 } catch (InterruptedException e) { e.printStackTrace(); } } } /** * * @Author 蔡文鋒 * @Data_Time 2015年7月25日 下午4:06:58 * @Description { 測(cè)試callable與runable方法的區(qū)別 } */ public void testNewCachedThreadPool_callable(){ ExecutorService es=Executors.newFixedThreadPool(10); try { // String result=es.submit(new MyCallable<String>()).get(); // System.out.println("callable result :"+result); String result=(String) es.submit(new ThreadPoolTask("")).get(); System.out.println("runable result :"+result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } public static void main(String[] args) { new JPoolLearn().testNewCachedThreadPool(); } } /** * 線程池執(zhí)行的任務(wù) */ class ThreadPoolTask implements Runnable { private static int consumeTaskSleepTime = 2000; // 保存任務(wù)所需要的數(shù)據(jù) private Object threadPoolTaskData; ThreadPoolTask(Object tasks) { this.threadPoolTaskData = tasks; } public void run() { System.out.println("start .." + threadPoolTaskData); try { // Sleep 2秒 模擬耗時(shí)操作 Thread.sleep(consumeTaskSleepTime); } catch (Exception e) { e.printStackTrace(); } threadPoolTaskData = null; } public Object getTask() { return this.threadPoolTaskData; } } /** * * @Project : JPool * @Package : com.sondon.mayi.jpool * @Class : MyCallable * @param <T> */ class MyCallable<T> implements Callable<T>{ @Override public T call() throws Exception { System.out.println( "開(kāi)始執(zhí)行Callable" ); return (T) "測(cè)試callable接口" ; } } |