1 引入線程池的原因
由于線程的生命周期中包括創建、就緒、運行、阻塞、銷毀階段,當我們待處理的任務數目較小時,我們可以自己創建幾個線程來處理相應的任務,但當有大量的任務時,由于創建、銷毀線程需要很大的開銷,運用線程池這些問題就大大的緩解了。
2 線程池的使用
我們只需要運用Executors類給我們提供的靜態方法,就可以創建相應的線程池:
1
2
3
4
5
|
public static ExecutorSevice newSingleThreadExecutor() public static ExecutorSevice newFixedThreadPool() public static ExecutorSevice newCachedThreadPool() |
newSingleThreadExecutor返回以個包含單線程的Executor,將多個任務交給此Exector時,這個線程處理完一個任務后接著處理下一個任務,若該線程出現異常,將會有一個新的線程來替代。
newFixedThreadPool返回一個包含指定數目線程的線程池,如果任務數量多于線程數目,那么沒有沒有執行的任務必須等待,直到有任務完成為止。
newCachedThreadPool根據用戶的任務數創建相應的線程來處理,該線程池不會對線程數目加以限制,完全依賴于JVM能創建線程的數量,可能引起內存不足。
我們只需要將待執行的任務放入run方法中即可,將Runnable接口的實現類交給線程池的execute方法,作為它的一個參數,如下所示:
1
2
3
4
5
6
|
Executor executor = Executors.newSingleThreadExecutor(); executor.execute( new Runnable(){ public void run(){ //執行的任務 } } |
如果需要給任務傳遞參數,可以通過創建一個Runnable接口的實現類來完成。
3.實例
(1):newSingleThreadExecutor
MyThread.java
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
|
publicclassMyThread extends Thread { @Override publicvoid run() { System.out.println(Thread.currentThread().getName() + "正在執行。。。" ); } } TestSingleThreadExecutor.java publicclassTestSingleThreadExecutor { publicstaticvoid main(String[] args) { //創建一個可重用固定線程數的線程池 ExecutorService pool = Executors. newSingleThreadExecutor(); //創建實現了Runnable接口對象,Thread對象當然也實現了Runnable接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); //將線程放入池中進行執行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); //關閉線程池 pool.shutdown(); } } |
輸出結果
1
2
3
4
5
|
pool-1-thread-1正在執行。。。 pool-1-thread-1正在執行。。。 pool-1-thread-1正在執行。。。 pool-1-thread-1正在執行。。。 pool-1-thread-1正在執行。。。 |
(2):newFixedThreadPool
TestFixedThreadPool.Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
publicclass TestFixedThreadPool { publicstaticvoid main(String[] args) { //創建一個可重用固定線程數的線程池 ExecutorService pool = Executors.newFixedThreadPool( 2 ); //創建實現了Runnable接口對象,Thread對象當然也實現了Runnable接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); //將線程放入池中進行執行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); //關閉線程池 pool.shutdown(); } } |
輸出結果
1
2
3
4
5
|
pool-1-thread-1正在執行。。。 pool-1-thread-2正在執行。。。 pool-1-thread-1正在執行。。。 pool-1-thread-2正在執行。。。 pool-1-thread-1正在執行。。。 |
(3): newCachedThreadPool
TestCachedThreadPool.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
publicclass TestCachedThreadPool { publicstaticvoid main(String[] args) { //創建一個可重用固定線程數的線程池 ExecutorService pool = Executors.newCachedThreadPool(); //創建實現了Runnable接口對象,Thread對象當然也實現了Runnable接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); //將線程放入池中進行執行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); //關閉線程池 pool.shutdown(); } } |
輸出結果:
1
2
3
4
5
|
pool-1-thread-2正在執行。。。 pool-1-thread-4正在執行。。。 pool-1-thread-3正在執行。。。 pool-1-thread-1正在執行。。。 pool-1-thread-5正在執行。。。 |
(4):newScheduledThreadPool
TestScheduledThreadPoolExecutor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
publicclass TestScheduledThreadPoolExecutor { publicstaticvoid main(String[] args) { ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor( 1 ); exec.scheduleAtFixedRate( new Runnable() { //每隔一段時間就觸發異常 @Override publicvoid run() { //throw new RuntimeException(); System.out.println( "================" ); } }, 1000 , 5000 , TimeUnit.MILLISECONDS); exec.scheduleAtFixedRate( new Runnable() { //每隔一段時間打印系統時間,證明兩者是互不影響的 @Override publicvoid run() { System.out.println(System.nanoTime()); } }, 1000 , 2000 , TimeUnit.MILLISECONDS); } } |
輸出結果
1
2
3
4
5
6
7
8
|
================ 8384644549516 8386643829034 8388643830710 ================ 8390643851383 8392643879319 8400643939383 |