本文會結合Future描述下線程池的使用場景
最近因爲換了工作,新工作需要更多的時間熟悉和上手,所以好久沒有寫文章了!
不過其實也一直有在看一些東西,比如Netty,spark源碼(其實以前有看過,但是太囫圇吞棗忘得差不多了) ,然後想起我以前寫過一個線程池相關的文章,但是對於線程池的使用只是一筆帶過,所以今天想具體來寫寫
【java】線程池概念,如何使用線程池?:https://blog.csdn.net/lsr40/article/details/101428779
案例:
曾經做過這麼一個案例,就是通過用戶傳入的參數,實時構建一份數據報表,這個功能肯定是異步的,相當於用戶調用了一個create方法把參數傳入進來,就直接返回了,不過後臺會啓動第一個線程池,來根據獲得的參數實際查數據庫,創建數據報表,保存到數據庫,然後又啓動了一個線程池(回調方法),這個線程池裏面使用了Future的get方法來等待第一個線程池完畢,並且將create的記錄修改爲成功或者失敗,並且記錄相關原因!
話不多說!下面,我會用六個例子,來演示Future的用法(我上面說的案例,用的是第五種模型,只不過FutureTask我們又自己封裝了一層,在裏面做了時間的記錄,日誌的打印,或者一些前置的初始化操作等待)
代碼示例:
package com.study.asyn;
import java.util.concurrent.*;
/**
* Created with IntelliJ IDEA
* Description:
* User: lsr
* Date: 2020/6/15
* Time: 18:46
*/
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
System.out.println("主線程開始工作:");
long startTime = System.currentTimeMillis();
ExecutorService executorService = Executors.newFixedThreadPool(1);
//newThreadDemo(executorService);
//futureGetDemo(executorService);
//futureGetAndTimeOutDemo(executorService);
//futureGetAndCallableDemo(executorService);
//callbackDemo(executorService);
futureTaskDemo(executorService);
long stopTime = System.currentTimeMillis();
System.out.println("主線程結束,耗時:"+(stopTime - startTime)+"ms");
//關閉線程
executorService.shutdown();
}
/**
* 第一種,無所謂線程執行是否結束,不阻塞
* 打印結果:
* 主線程開始工作:
* 主線程結束,耗時:3ms
* 線程中的任務,開始運行!
* 正在執行!
* 線程中的任務,結束執行!
* @param executorService
* @throws ExecutionException
* @throws InterruptedException
*/
private static void newThreadDemo(ExecutorService executorService) throws ExecutionException, InterruptedException {
executorService.submit(new Runnable() {
public void run() {
System.out.println("線程中的任務,開始運行!");
doSomeThing();
System.out.println("線程中的任務,結束執行!");
}
});
}
/**
* 第二種,通過future的get方法,會阻塞等到執行完畢!
* 主線程開始工作:
* 線程中的任務,開始運行!
* 正在執行!
* 線程中的任務,結束執行!
* null
* 主線程結束,耗時:3005ms
* @param executorService
* @throws ExecutionException
* @throws InterruptedException
*/
private static void futureGetDemo(ExecutorService executorService) throws ExecutionException, InterruptedException {
Future<?> future = executorService.submit(new Runnable() {
public void run() {
System.out.println("線程中的任務,開始運行!");
doSomeThing();
System.out.println("線程中的任務,結束執行!");
}
});
Object o = future.get();
System.out.println(o);
}
/**
* 第三種,通過future的get方法,並且有超時時間,會阻塞等到執行完畢!
*
* 主線程開始工作:
* 線程中的任務,開始運行!
* 正在執行!
* 主線程結束,耗時:1007ms
* java.util.concurrent.TimeoutException
* at java.util.concurrent.FutureTask.get(FutureTask.java:205)
* at com.study.asyn.FutureTest.futureGetAndTimeOutDemo(FutureTest.java:99)
* at com.study.asyn.FutureTest.main(FutureTest.java:21)
* 線程中的任務,結束執行!
* @param executorService
* @throws ExecutionException
* @throws InterruptedException
*/
private static void futureGetAndTimeOutDemo(ExecutorService executorService) throws ExecutionException, InterruptedException {
Future<?> future = executorService.submit(new Runnable() {
public void run() {
System.out.println("線程中的任務,開始運行!");
doSomeThing();
System.out.println("線程中的任務,結束執行!");
}
});
Object o = null;
try {
o = future.get(1,TimeUnit.SECONDS);
System.out.println(o);
} catch (TimeoutException e) {
//true和false的區別大家可以看源碼中的註釋
//true就是中斷當前執行的線程,false就是讓線程執行完
future.cancel(false);
e.printStackTrace();
}
}
/**
* 第四種,通過future的get並且配合Callable方法,獲得線程中return結果,會阻塞等到執行完畢!
* 主線程開始工作:
* 線程中的任務,開始運行!
* 正在執行!
* 線程中的任務,結束執行!
* 返回值~
* 主線程結束,耗時:3005ms
* @param executorService
* @throws ExecutionException
* @throws InterruptedException
*/
private static void futureGetAndCallableDemo(ExecutorService executorService) throws ExecutionException, InterruptedException {
Future<?> future = executorService.submit(new Callable<String>() {
public String call() throws Exception {
System.out.println("線程中的任務,開始運行!");
doSomeThing();
System.out.println("線程中的任務,結束執行!");
return "返回值~";
}
});
String returnValue = (String)future.get();
System.out.println(returnValue);
}
/**
* 第五種,想在獲得future的get結果之後,再做一些處理,但是又不想阻塞主線程,通過回調,啓動另一個線程來做這個事情
*
* 主線程開始工作:
* 線程中的任務,開始運行!
* 正在執行!
* 主線程結束,耗時:5ms
* 線程中的任務,結束執行!
* 返回值~
* 成功!
*
* @param executorService
* @throws ExecutionException
* @throws InterruptedException
*/
private static void callbackDemo(ExecutorService executorService) throws ExecutionException, InterruptedException {
ExecutorService fixExecutorService = Executors.newFixedThreadPool(1);
final Future<?> future = executorService.submit(new Callable<String>() {
public String call() throws Exception {
System.out.println("線程中的任務,開始運行!");
doSomeThing();
System.out.println("線程中的任務,結束執行!");
return "返回值~";
}
});
fixExecutorService.submit(new Runnable() {
public void run() {
String returnValue = null;
try {
returnValue = (String)future.get();
System.out.println(returnValue);
System.out.println("成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
});
fixExecutorService.shutdown();
}
/**
* 第六種,之前線程都是使用submit提交任務,以此獲得返回Future對象
* 但是使用升級版的FutureTask+線程池的execute方法,也能得到返回值
*
* 主線程開始工作:
* 線程中的任務,開始運行!
* 正在執行!
* 線程中的任務,結束執行!
* 返回值~
* 主線程結束,耗時:3005ms
*
* @param executorService
* @throws ExecutionException
* @throws InterruptedException
*/
private static void futureTaskDemo(ExecutorService executorService) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
System.out.println("線程中的任務,開始運行!");
doSomeThing();
System.out.println("線程中的任務,結束執行!");
return "返回值~";
}
});
//execute方法雖然沒有返回值,但是因爲FutureTask實現類Future+Runnable,
// 所以也可以直接調用execute方法計算,再調用get獲得返回結果
executorService.execute(futureTask);
String s = futureTask.get();
System.out.println(s);
}
private static void doSomeThing(){
try {
System.out.println("正在執行!");
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
結語:
好了,沒有什麼多餘的東西要在這篇文章裏說明了(每一種方法我都寫好了註釋,我也都跑過了,沒什麼問吐),大家要是有什麼疑問,歡迎留言!
菜雞一隻,努力提升,學習中!!
剛開始工作的時候,覺得有些人做一些朝九晚五不過錢少的工作,看起來一點都不nice,實際自己工作了幾年之後,認真想想那樣的生活又何嘗不痛快呢?大家都在享受人生,千人千面,有人因爲工作有所成就而快樂,有人因爲愛好有所精進而快樂,有人因爲教書育人而快樂,又有人因爲遊戲漲段而快樂,其實只要收入能夠維持自己物質上支出,那做什麼又有什麼區別呢?並沒有那麼多人想在工作中,實現自己的理想和抱負,完成個人價值的昇華。
想起初中語文老師問我,以後的目標是什麼?
讀好書,做好人,生好下一代,培養之,那這輩子的使命不也算完成了?
有時候躺在草地上,呆呆的望向天空,輕柔的雲朵,綿綿的細雨,徜徉在花海中,感受大自然高山流水,又何嘗不是一種人生哲學呢?
下班了,溜了溜了!