什么原因使我們不得不使用線程池?
個人認為主要原因是:短時間內需要處理的任務數量很多
使用線程池的好處:
1.減少在創建和銷毀線程上所花的時間以及系統資源的開銷
2.如不使用線程池,有可能造成系統創建大量線程而導致消耗完系統內存
以下是Java自帶的幾種線程池:
1、newFixedThreadPool 創建一個指定工作線程數量的線程池。
每當提交一個任務就創建一個工作線程,如果工作線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中。
2、newCachedThreadPool 創建一個可緩存的線程池。
這種類型的線程池特點是:
1).工作線程的創建數量幾乎沒有限制(其實也有限制的,數目為Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。
2).如果長時間沒有往線程池中提交任務,即如果工作線程空閑了指定的時間(默認為1分鐘),則該工作線程將自動終止。終止后,如果你又提交了新的任務,則線程池重新創建一個工作線程。
3、newSingleThreadExecutor 創建一個單線程化的Executor,即只創建唯一的工作者線程來執行任務,如果這個線程異常結束,會有另一個取代它,保證順序執行(我覺得這點是它的特色)。
單工作線程最大的特點是可保證順序地執行各個任務,并且在任意給定的時間不會有多個線程是活動的 。
4、newScheduleThreadPool 創建一個定長的線程池,而且支持定時的以及周期性的任務執行,類似于Timer。
總結:
一.FixedThreadPool是一個典型且優秀的線程池,它具有線程池提高程序效率和節省創建線程時所耗的開銷的優點。但在線程池空閑時,即線程池中沒有可運行任務時,它不會釋放工作線程,還會占用一定的系統資源。
二.CachedThreadPool的特點就是在線程池空閑時,即線程池中沒有可運行任務時,它會釋放工作線程,從而釋放工作線程所占用的資源。但是,但當出現新任務時,又要創建一新的工作線程,又要一定的系統開銷。并且,在使用CachedThreadPool時,一定要注意控制任務的數量,否則,由于大量線程同時運行,很有會造成系統癱瘓。
Java線程池 ThreadPoolExecutor使用實例
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, //線程池維護線程的最少數量 * int maximumPoolSize, //線程池維護線程的最大數量 * long keepAliveTime, //線程池維護線程所允許的空閑時間 * TimeUnit unit, //線程池維護線程所允許的空閑時間的單位 * BlockingQueue<Runnable> workQueue, //線程池所使用的緩沖隊列 * RejectedExecutionHandler handler //線程池對拒絕任務的處理策略 ) */ ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.DiscardOldestPolicy() ); for (int i = 1; i <= produceTaskMaxNumber; i++) { try { // 產生一個任務,并將其加入到線程池 String task = "task---" + i; threadPool.execute(new ThreadPoolTask(task)); System.out.println("activeCount :"+ threadPool.getActiveCount()); // 便于觀察,等待一段時間 Thread.sleep(produceTaskSleepTime); } catch (Exception e) { e.printStackTrace(); } } //查看當前的線程池狀況 while(true){ try { Thread.sleep(3000); System.out.println("pool size :"+threadPool.getPoolSize());//線程池中線程數量 System.out.println("active count :"+threadPool.getActiveCount());//線程池中活動的線程數量 } catch (InterruptedException e) { e.printStackTrace(); } } } /** * * @Author 蔡文鋒 * @Data_Time 2015年7月25日 下午4:06:28 * @Description { 測試不同線程池模式 } */ 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++) { // 產生一個任務,并將其加入到線程池 String task = "task---" + i; threadPool.execute(new ThreadPoolTask(task)); System.out.println("activeCount :"); // 便于觀察,等待一段時間 Thread.sleep(produceTaskSleepTime); } } catch (InterruptedException e) { e.printStackTrace(); } //查看當前的線程池狀況 while(true){ try { Thread.sleep(3000); System.out.println("pool size :"+threadPool.getPoolSize());//線程池中線程數量 System.out.println("active count :"+threadPool.getActiveCount());//線程池中活動的線程數量 } catch (InterruptedException e) { e.printStackTrace(); } } } /** * * @Author 蔡文鋒 * @Data_Time 2015年7月25日 下午4:06:58 * @Description { 測試callable與runable方法的區別 } */ 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(); } } /** * 線程池執行的任務 */ class ThreadPoolTask implements Runnable { private static int consumeTaskSleepTime = 2000; // 保存任務所需要的數據 private Object threadPoolTaskData; ThreadPoolTask(Object tasks) { this.threadPoolTaskData = tasks; } public void run() { System.out.println("start .." + threadPoolTaskData); try { // Sleep 2秒 模擬耗時操作 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( "開始執行Callable" ); return (T) "測試callable接口" ; } } |