DP_多段 “連續子段和” 的最大值問題
java 建立執行緒池
執行緒池都是通過執行緒池工廠建立,再呼叫執行緒池中的方法獲取執行緒,再通過執行緒去執行任務方法。
Executors:執行緒池建立工廠類
public static ExecutorServicenewFixedThreadPool(int nThreads):返回執行緒池物件
ExecutorService:執行緒池類
Future<?> submit(Runnable task):獲取執行緒池中的某一個執行緒物件,並執行
Future 介面:用來記錄執行緒任務執行完畢後產生的結果。執行緒池建立與使用
這裡介紹兩種使用執行緒池建立執行緒的方法
1):使用Runnable介面建立執行緒池
使用執行緒池中執行緒物件的步驟:
1、建立執行緒池物件
2、建立 Runnable 介面子類物件
3、提交 Runnable 介面子類物件
4、關閉執行緒池
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class TaskRunnable implements Runnable{ @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("自定義執行緒任務在執行"+i); } } } public class Test { public static void main(String[] args) { //建立執行緒池物件 引數5,代表有5個執行緒的執行緒池 ExecutorService service = Executors.newFixedThreadPool(5); //建立Runnable執行緒任務物件 TaskRunnable task = new TaskRunnable(); //從執行緒池中獲取執行緒物件 service.submit(task); System.out.println("----------------------"); //再獲取一個執行緒物件 service.submit(task); //關閉執行緒池 service.shutdown(); } }
2)使用Callable介面建立執行緒池
Callable介面:與Runnable介面功能相似,用來指定執行緒的任務。其中的call()方法,用來返回執行緒任務執行完畢後的結果,call方法可丟擲異常。
ExecutorService:執行緒池類
Future submit(Callable task):獲取執行緒池中的某一個執行緒物件,並執行執行緒中的 call() 方法 Future 介面:用來記錄執行緒任務執行完畢後產生的結果。執行緒池建立與使用
使用執行緒池中執行緒物件的步驟:
1、建立執行緒池物件
2、建立 Callable 介面子類物件
3、提交 Callable 介面子類物件
4、關閉執行緒池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Callable;
class TaskCallable implements Callable<Object>{
@Override
public Object call() throws Exception {
for (int i = 0; i < 1000; i++) {
System.out.println("自定義執行緒任務在執行"+i);
}
return null;
}
}
public class Test{
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(3);
TaskCallable c = new TaskCallable();
//執行緒池中獲取執行緒物件,呼叫run方法
service.submit(c);
//再獲取一個
service.submit(c);
//關閉執行緒池
service.shutdown();
}
}
用 CompletableFuture 來解決回撥的問題。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
public class CompletableFutureDemo {
public static void main(String[] args) throws InterruptedException {
long l = System.currentTimeMillis();
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("執行耗時操作...");
timeConsumingOperation();
return 100;
});
completableFuture.whenComplete((result, e) -> {
System.out.println("結果:" + result);
});
System.out.println("主執行緒運算耗時:" + (System.currentTimeMillis() - l) + " ms");
new CountDownLatch(1).await();
}
static void timeConsumingOperation() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Future 的侷限性
-
不能手動完成
當你寫了一個函式,用於通過一個遠端API獲取一個電子商務產品最新價格。因為這個 API 太耗時,你把它允許在一個獨立的執行緒中,並且從你的函式中返回一個 Future。現在假設這個API服務宕機了,這時你想通過該產品的最新快取價格手工完成這個Future 。你會發現無法這樣做。 -
Future 的結果在非阻塞的情況下,不能執行更進一步的操作
Future 不會通知你它已經完成了,它提供了一個阻塞的 get() 方法通知你結果。你無法給 Future 植入一個回撥函式,當 Future 結果可用的時候,用該回調函式自動的呼叫 Future 的結果。
3.多個 Future 不能串聯在一起組成鏈式呼叫 有時候你需要執行一個長時間執行的計算任務,並且當計算任務完成的時候,你需要把它的計算結果傳送給另外一個長時間執行的計算任務等等。你會發現你無法使用 Future 建立這樣的一個工作流。
4.不能組合多個 Future 的結果 假設你有10個不同的Future,你想並行的執行,然後在它們執行未完成後執行一些函式。你會發現你也無法使用 Future 這樣做。
5.沒有異常處理 Future API 沒有任務的異常處理結構居然有如此多的限制,幸好我們有CompletableFuture,你可以使用 CompletableFuture 達到以上所有目的。
CompletableFuture
CompletableFuture 實現了 Future 和 CompletionStage介面,並且提供了許多關於建立,鏈式呼叫和組合多個 Future 的便利方法集,而且有廣泛的異常處理支援。
阿里推薦使用
ExecutorService executor =new ThreadPoolExecutor(........)