標籤:遊泳池 return sum except over image 封裝 service string
線程池概念
線程池,其實就是一個容納多個線程的容器,其中的線程可以反覆使用,省去了頻繁建立線程對象的操作,無需反覆建立線程而消耗過多資源。
我們詳細的解釋一下為什麼要使用線程池?(程式最佳化)
在java中,如果每個請求到達就建立一個新線程,開銷是相當大的。在實際使用中,建立和銷毀線程花費的時間和消耗的系統資源都相當大,甚至可能要比在處理實際的使用者請求的時間和資源要多的多。除了建立和銷毀線程的開銷之外,活動的線程也需要消耗系統資源。如果在一個jvm裡建立太多的線程,可能會使系統由於過度消耗記憶體或“切換過度”而導致系統資源不足。為了防止資源不足,需要採取一些辦法來限制任何給定時刻處理的請求數目,儘可能減少建立和銷毀線程的次數,特別是一些資源耗費比較大的線程的建立和銷毀,盡量利用已有對象來進行服務。
線程池主要用來解決線程生命週期開銷問題和資源不足問題。通過對多個任務重複使用線程,線程建立的開銷就被分攤到了多個任務上了,而且由於在請求到達時線程已經存在,所以消除了線程建立所帶來的延遲。這樣,就可以立即為請求服務,使用應用程式響應更快。另外,通過適當的調整線程中的線程數目可以防止出現資源不足的情況。
使用線程池方式--Runnable介面
通常,線程池都是通過線程池工廠建立,再調用線程池中的方法擷取線程,再通過線程去執行任務方法。
l Executors:線程池建立工廠類
n public static ExecutorService newFixedThreadPool(int nThreads):返回線程池對象
l ExecutorService:線程池類
n Future<?> submit(Runnable task):擷取線程池中的某一個線程對象,並執行
l Future介面:用來記錄線程任務執行完畢後產生的結果。線程池建立與使用
l 使用線程池中線程對象的步驟:
n 建立線程池對象
n 建立Runnable介面子類對象(建立任務)
n 提交Runnable介面子類對象(執行任務)
n 關閉線程池
代碼示範:
public class ThreadPoolDemo {
public static void main(String[] args) {
//建立線程池對象
ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
//建立Runnable執行個體對象
MyRunnable r = new MyRunnable();
//自己建立線程對象的方式
//Thread t = new Thread(r);
//t.start(); ---> 調用MyRunnable中的run()
//從線程池中擷取線程對象,然後調用MyRunnable中的run()
service.submit(r);
//再擷取個線程對象,調用MyRunnable中的run()
service.submit(r);
service.submit(r);
//注意:submit方法調用結束後,程式並不終止,是因為線程池控制了線程的關閉。將使用完的線程又歸還到了線程池中
//關閉線程池
//service.shutdown();
}
}
l Runnable介面實作類別
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("教我遊泳,交完後,教練回到了遊泳池");
}
}
使用線程池方式—Callable介面(專用於線程池)
l Callable介面:與Runnable介面功能相似,用來指定線程的任務。其中的call()方法,用來返回線程任務執行完畢後的結果,call方法可拋出異常可設定傳回值。
l ExecutorService:線程池類
n <T> Future<T> submit(Callable<T> task):擷取線程池中的某一個線程對象,並執行線程中的call()方法
l Future介面:用來記錄線程任務執行完畢後產生的結果。線程池建立與使用
l 使用線程池中線程對象的步驟:
n 建立線程池對象
n 建立Callable介面子類對象
n 提交Callable介面子類對象
n 關閉線程池
代碼示範:
public class ThreadPoolDemo {
public static void main(String[] args) {
//建立線程池對象
ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
//建立Callable對象
MyCallable c = new MyCallable();
//從線程池中擷取線程對象,然後調用MyRunnable中的run()
service.submit(c);
//再擷取個教練
service.submit(c);
service.submit(c);
//注意:submit方法調用結束後,程式並不終止,是因為線程池控制了線程的關閉。將使用完的線程又歸還到了線程池中
//關閉線程池
//service.shutdown();
}
}
l Callable介面實作類別,call方法可拋出異常、返回線程任務執行完畢後的結果
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;
}
}
線程池練習:返回兩個數相加的結果
要求:通過線程池中的線程對象,使用Callable介面完成兩個數求和操作
l Future介面:用來記錄線程任務執行完畢後產生的結果。
n V get() 擷取Future對象中封裝的資料結果
代碼示範:
public class ThreadPoolDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//建立線程池對象
ExecutorService threadPool = Executors.newFixedThreadPool(2);
//建立一個Callable介面子類對象
//MyCallable c = new MyCallable();
MyCallable c = new MyCallable(100, 200);
MyCallable c2 = new MyCallable(10, 20);
//擷取線程池中的線程,調用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);
}
}
l Callable介面實作類別
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;
}
}
java ->多線程_線程池