一.介紹
線程池是一種多線程處理形式狮荔,處理過程中將任務添加到隊列,然后在創(chuàng)建線程后自動啟動這些任務狸捕。線程池線程都是后臺線程。每個線程都使用默認的堆棧大小众雷,以默認的優(yōu)先級運行灸拍,并處于多線程單元中做祝。如果某個線程在托管代碼中空閑(如正在等待某個事件),則線程池將插入另一個輔助線程來使所有處理器保持繁忙。如果所有線程池線程都始終保持繁忙鸡岗,但隊列中包含掛起的工作混槐,則線程池將在一段時間后創(chuàng)建另一個輔助線程但線程的數(shù)目永遠不會超過最大值。超過最大值的線程可以排隊轩性,但他們要等到其他線程完成后才啟動声登。
二.知識點介紹
1、線程池概念
2揣苏、使用線程池方式--Runnable接口
3悯嗓、使用線程池方式—Callable接口
4、線程池練習:返回兩個數(shù)相加的結果
三.上課視頻對應說明文檔
1卸察、線程池概念
線程池绅作,其實就是一個容納多個線程的容器,其中的線程可以反復使用蛾派,省去了頻繁創(chuàng)建線程對象的操作俄认,無需反復創(chuàng)建線程而消耗過多資源。
我們詳細的解釋一下為什么要使用線程池洪乍?
在java中眯杏,如果每個請求到達就創(chuàng)建一個新線程,開銷是相當大的壳澳。在實際使用中岂贩,創(chuàng)建和銷毀線程花費的時間和消耗的系統(tǒng)資源都相當大,甚至可能要比在處理實際的用戶請求的時間和資源要多的多巷波。除了創(chuàng)建和銷毀線程的開銷之外萎津,活動的線程也需要消耗系統(tǒng)資源。如果在一個jvm里創(chuàng)建太多的線程抹镊,可能會使系統(tǒng)由于過度消耗內(nèi)存或“切換過度”而導致系統(tǒng)資源不足锉屈。為了防止資源不足,需要采取一些辦法來限制任何給定時刻處理的請求數(shù)目垮耳,盡可能減少創(chuàng)建和銷毀線程的次數(shù)颈渊,特別是一些資源耗費比較大的線程的創(chuàng)建和銷毀,盡量利用已有對象來進行服務终佛。
線程池主要用來解決線程生命周期開銷問題和資源不足問題俊嗽。通過對多個任務重復使用線程,線程創(chuàng)建的開銷就被分攤到了多個任務上了铃彰,而且由于在請求到達時線程已經(jīng)存在绍豁,所以消除了線程創(chuàng)建所帶來的延遲。這樣牙捉,就可以立即為請求服務竹揍,使用應用程序響應更快敬飒。另外,通過適當?shù)恼{(diào)整線程中的線程數(shù)目可以防止出現(xiàn)資源不足的情況鬼佣。
2驶拱、使用線程池方式--Runnable接口
通常霜浴,線程池都是通過線程池工廠創(chuàng)建晶衷,再調(diào)用線程池中的方法獲取線程,再通過線程去執(zhí)行任務方法阴孟。
Executors:線程池創(chuàng)建工廠類
public static ExecutorService newFixedThreadPool(int nThreads):返回線程池對象
ExecutorService:線程池類
Future<?> submit(Runnable task):獲取線程池中的某一個線程對象晌纫,并執(zhí)行
Future接口:用來記錄線程任務執(zhí)行完畢后產(chǎn)生的結果。線程池創(chuàng)建與使用
使用線程池中線程對象的步驟:
(1)創(chuàng)建線程池對象
(2)創(chuàng)建Runnable接口子類對象
(3)提交Runnable接口子類對象
(4)關閉線程池
代碼示例:
public class ThreadPoolDemo {
public static void main(String[] args) {
//創(chuàng)建線程池對象
ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
//創(chuàng)建Runnable實例對象
MyRunnable r = new MyRunnable();
//自己創(chuàng)建線程對象的方式
//Thread t = new Thread(r);
//t.start(); ---> 調(diào)用MyRunnable中的run()
//從線程池中獲取線程對象,然后調(diào)用MyRunnable中的run()
service.submit(r);
//再獲取個線程對象永丝,調(diào)用MyRunnable中的run()
service.submit(r);
service.submit(r);
//注意:submit方法調(diào)用結束后锹漱,程序并不終止,是因為線程池控制了線程的關閉慕嚷。將使用完的線程又歸還到了線程池中
//關閉線程池
//service.shutdown();
}
}
Runnable接口實現(xiàn)類
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("我要一個教練");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("教練來了: " +Thread.currentThread().getName());
System.out.println("教我游泳,交完后哥牍,教練回到了游泳池");
}
}
3、使用線程池方式—Callable接口
Callable接口:與Runnable接口功能相似喝检,用來指定線程的任務嗅辣。其中的call()方法,用來返回線程任務執(zhí)行完畢后的結果挠说,call方法可拋出異常澡谭。
ExecutorService:線程池類
<T> Future<T> submit(Callable<T> task):獲取線程池中的某一個線程對象,并執(zhí)行線程中的call()方法
Future接口:用來記錄線程任務執(zhí)行完畢后產(chǎn)生的結果损俭。線程池創(chuàng)建與使用
使用線程池中線程對象的步驟:
(1)創(chuàng)建線程池對象
(2)創(chuàng)建Callable接口子類對象
(3)提交Callable接口子類對象
(4)關閉線程池
代碼示例:
public class ThreadPoolDemo {
public static void main(String[] args) {
//創(chuàng)建線程池對象
ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
//創(chuàng)建Callable對象
MyCallable c = new MyCallable();
//從線程池中獲取線程對象,然后調(diào)用MyRunnable中的run()
service.submit(c);
//再獲取個教練
service.submit(c);
service.submit(c);
//注意:submit方法調(diào)用結束后蛙奖,程序并不終止,是因為線程池控制了線程的關閉杆兵。將使用完的線程又歸還到了線程池中
//關閉線程池
//service.shutdown();
}
}
Callable接口實現(xiàn)類,call方法可拋出異常雁仲、返回線程任務執(zhí)行完畢后的結果
public class MyCallable implements Callable {
@Override
public Object call() throws Exception {
System.out.println("我要一個教練:call");
Thread.sleep(2000);
System.out.println("教練來了: "? ? ? +Thread.currentThread().getName());
System.out.println("教我游泳,交完后,教練回到了游泳池");
return null;
}
}
4、線程池練習:返回兩個數(shù)相加的結果
要求:通過線程池中的線程對象琐脏,使用Callable接口完成兩個數(shù)求和操作
Future接口:用來記錄線程任務執(zhí)行完畢后產(chǎn)生的結果伯顶。線程池創(chuàng)建與使用
V get() 獲取Future對象中封裝的數(shù)據(jù)結果
代碼示例:
public class ThreadPoolDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//創(chuàng)建線程池對象
ExecutorService threadPool = Executors.newFixedThreadPool(2);
//創(chuàng)建一個Callable接口子類對象
//MyCallable c = new MyCallable();
MyCallable c = new MyCallable(100, 200);
MyCallable c2 = new MyCallable(10, 20);
//獲取線程池中的線程,調(diào)用Callable接口子類對象中的call()方法, 完成求和操作
//<Integer> Future<Integer> submit(Callable<Integer> task)
// Future 結果對象
Future<Integer> result = threadPool.submit(c);
//此 Future 的 get 方法所返回的結果類型
Integer sum = result.get();
System.out.println("sum=" + sum);
//再演示
result = threadPool.submit(c2);
sum = result.get();
System.out.println("sum=" + sum);
//關閉線程池(可以不關閉)
}
}
Callable接口實現(xiàn)類
public class MyCallable implements Callable<Integer> {
//成員變量
int x = 5;
int y = 3;
//構造方法
public MyCallable(){
}
public MyCallable(int x, int y){
this.x = x;
this.y = y;
}
@Override
public Integer call() throws Exception {
return x+y;
}
}