java中Future使用方法舉例詳細介紹
一、什么是Future?
在并發(fā)編程中,可以通過Future對象來異步獲取結果。
使用Thread或runnable接口都不能獲取異步的執(zhí)行結果,因為他們沒有返回值。而通過實現(xiàn)Callable接口和Future就可以獲取異步執(zhí)行的結果,當異步執(zhí)行結束后,返回結果將保存在Future中。使用Future就可以讓我們暫時去處理其他的任務而無需一直等待結果,等異步任務執(zhí)行完畢再返回其結果。
二、Future中的get方法
1、get方法
獲取任務結束后返回的結果,如果調用時,任務還沒有結束,則會進行阻塞線程,直到任務完成。該阻塞是可以被打斷的,打斷的線程是調用get方法的線程,被打斷后原任務會依舊繼續(xù)執(zhí)行。
V get() throws InterruptedException, ExecutionException;
2、指定時間的get方法
獲取任務結束后返回的結果,如果調用時,任務還沒有結束,則會進行阻塞線程,等待一定時間,如果在規(guī)定時間內任務結束則返回結果,否則拋出TimeoutException,超時后任務依舊會繼續(xù)執(zhí)行。該阻塞是可以被打斷的,打斷的線程是調用get方法的線程,被打斷后原任務會依舊繼續(xù)執(zhí)行。
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
三、Future代碼示例
步驟1:創(chuàng)建一個線程池
public class AsyncTaskExecutor {
/**
* 核心線程數(shù)
*/
private static final int corePoolSize = 10;
/**
* 最大線程數(shù)
*/
private static final int maxPoolSize = 30;
/**
* 空閑線程回收時間
* 空閑線程是指:當前線程池中超過了核心線程數(shù)之后,多余的空閑線程的數(shù)量
*/
private static final int keepAliveTime = 100;
/**
* 任務隊列/阻塞隊列
*/
private static final int blockingQueueSize = 99999;
private static final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(blockingQueueSize),
new ThreadFactoryBuilder().setNameFormat("AsyncTaskThread" + "-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
/**
* 異步任務執(zhí)行
*
* @param task
*/
public static void execute(Runnable task) {
executorPool.execute(task);
}
/**
* 異步執(zhí)行任務Callable, 通過Future獲取結果
*
* @param task
* @param <T>
* @return
*/
public static <T> Future<T> submit(Callable<T> task) {
return executorPool.submit(task);
}
/**
* 異步執(zhí)行任務Runnable,通過Future獲取結果
*
* @param task
* @return
*/
public static Future<?> submit(Runnable task) {
return executorPool.submit(task);
}
}步驟2:編寫測試類
@Test
public void test2() {
try {
Future<String> future = AsyncTaskExecutor.submit(() -> {
log.info("[Future Task] future task start...");
try {
//模擬任務執(zhí)行
Thread.sleep(5000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
log.info("[Future Task] future task end...");
return "Task completed...";
});
//執(zhí)行其他任務
log.info("[Main Thread] main thread is running...");
//使用future阻塞等待任務完成,并獲取結果
String futureResult = future.get();
log.info("[Main Thread] {}", futureResult);
}catch (Exception e) {
e.printStackTrace();
}
}
步驟3:查看結果
2024-05-28 10:58:23.633 INFO 1184 --- [ main] com.example.demo.dao.UserDaoTest : [Main Thread] main thread is running... 2024-05-28 10:58:23.633 INFO 1184 --- [yncTaskThread-0] com.example.demo.dao.UserDaoTest : [Future Task] future task start... 2024-05-28 10:58:28.633 INFO 1184 --- [yncTaskThread-0] com.example.demo.dao.UserDaoTest : [Future Task] future task end... 2024-05-28 10:58:28.634 INFO 1184 --- [ main] com.example.demo.dao.UserDaoTest : [Main Thread] Task completed...
四、ListenableFuture
public class AsyncTaskExecutor {
/**
* 核心線程數(shù)
*/
private static final int corePoolSize = 10;
/**
* 最大線程數(shù)
*/
private static final int maxPoolSize = 30;
/**
* 空閑線程回收時間
* 空閑線程是指:當前線程池中超過了核心線程數(shù)之后,多余的空閑線程的數(shù)量
*/
private static final int keepAliveTime = 100;
/**
* 任務隊列/阻塞隊列
*/
private static final int blockingQueueSize = 99999;
private static final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(blockingQueueSize),
new ThreadFactoryBuilder().setNameFormat("AsyncTaskThread" + "-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
/**
* 創(chuàng)建一個ListeningExecutorService,用于執(zhí)行異步任務
* (通過submit提交任務,以ListenableFuture獲取結果)
*/
private static final ListeningExecutorService LISTENING_EXECUTOR = MoreExecutors.listeningDecorator(executorPool);
/**
* 異步任務執(zhí)行
*
* @param task
*/
public static void execute(Runnable task) {
executorPool.execute(task);
}
/**
* 異步執(zhí)行任務Callable, 通過ListenableFuture獲取結果
*
* @param task
* @param <T>
* @return
*/
public static <T> ListenableFuture<T> submit(Callable<T> task) {
return LISTENING_EXECUTOR.submit(task);
}
/**
* 異步執(zhí)行任務Runnable,通過Future獲取結果
*
* @param task
* @return
*/
public static ListenableFuture<?> submit(Runnable task) {
return LISTENING_EXECUTOR.submit(task);
}
} //示例1:
@Test
public void test2() {
ListenableFuture<School> listenableFuture1 = AsyncTaskExecutor.submit(() -> {
try {
//模擬任務執(zhí)行
Thread.sleep(2000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
return new School("DSchool");
});
ListenableFuture<School> listenableFuture2 = AsyncTaskExecutor.submit(() -> {
try {
//模擬任務執(zhí)行
Thread.sleep(3000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
return new School("ESchool");
});
//阻塞等待,直到listenableFuture1 和 listenableFuture2都獲取到結果后或其中一個異常
Futures.successfulAsList(listenableFuture1, listenableFuture2).get();
School resSchool1 = listenableFuture1.get();
School resSchool2 = listenableFuture2.get();
log.info("[Main Thread] result1 is {}", JSON.toJSONString(resSchool1));
log.info("[Main Thread] result2 is {}", JSON.toJSONString(resSchool2));
//任意位置即時設定ListenableFuture的返回結果
ListenableFuture<School> listenableFuture3 = Futures.immediateFuture(new School("aaa"));
ListenableFuture<School> listenableFuture4 = Futures.immediateFailedFuture(new Exception("eeee"));
log.info("[Main Thread] listenableFuture3 is {}", listenableFuture3.get());
log.info("[Main Thread] listenableFuture4 is {}", listenableFuture4.get());
}catch (Exception e) {
e.printStackTrace();
}
}
//示例2:
public static void main(String[] args) {
// 創(chuàng)建一個ListeningExecutorService,用于執(zhí)行異步任務
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
// 提交一個異步任務,并得到ListenableFuture對象
ListenableFuture<String> listenableFuture = executor.submit(() -> {
// 模擬耗時操作
Thread.sleep(2000);
return "Result of the asynchronous computation";
});
// 注冊異步操作完成時的回調函數(shù)
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("Result: " + result);
executor.shutdown(); // 關閉executor
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
executor.shutdown(); // 關閉executor
}
}, executor);
}
五、CompletableFuture
//示例1:
public static void main(String[] args) {
// 創(chuàng)建一個CompletableFuture對象
CompletableFuture<School> completableFuture = new CompletableFuture<>();
// 異步任務:模擬一個耗時操作
new Thread(() -> {
try {
// 模擬耗時操作
Thread.sleep(2000);
// 完成CompletableFuture并設置值
completableFuture.complete(new School("completableSchool"));
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 在這里等待異步任務的結果并輸出
try {
School result = completableFuture.get();
log.info("[CompletableFuture] result is {}" ,result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
//示例2:
@Test
public void test2() {
try {
//創(chuàng)建一個CompletableFuture對象
CompletableFuture<School> schoolFuture = new CompletableFuture<>();
//任意位置即時設定CompletableFuture的返回結果
schoolFuture.complete(new School("FSchool"));
School school = schoolFuture.get();
log.info("[Main Thread] result is {}", JSON.toJSONString(school));
}catch (Exception e) {
log.info(e.getMessage());
}
}
六、SettableFuture
//示例1:
public static void main(String[] args) {
// 創(chuàng)建一個SettableFuture對象
SettableFuture<String> settableFuture = SettableFuture.create();
// 手動設置異步操作的結果
settableFuture.set("Result of the asynchronous computation");
// 注冊異步操作完成時的回調函數(shù)
settableFuture.addListener(() -> {
try {
String result = settableFuture.get(); // 獲取異步操作的結果
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}, Runnable::run);
}
//示例2:
@Test
public void test2() {
try {
//創(chuàng)建一個SettableFuture對象
SettableFuture<School> settableFuture = SettableFuture.create();
//任意位置即時設定SettableFuture的返回結果
settableFuture.set(new School("GSchool"));
School setSchool = settableFuture.get();
log.info("[Main Thread] setSchool is {}", JSON.toJSONString(setSchool));
}catch (Exception e) {
log.info(e.getMessage());
}
}總結
到此這篇關于java中Future使用方法的文章就介紹到這了,更多相關java中Future使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java客戶端通過HTTPS連接到Easysearch實現(xiàn)過程
這篇文章主要為大家介紹了Java客戶端通過HTTPS連接到Easysearch實現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
rabbitmq的消息持久化處理開啟,再關閉后,消費者啟動報錯問題
這篇文章主要介紹了rabbitmq的消息持久化處理開啟,再關閉后,消費者啟動報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
IDEA導入Springboot項目,注解和pom文件不識別的解決
這篇文章主要介紹了IDEA導入Springboot項目,注解和pom文件不識別的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
Java并發(fā)編程之LongAdder執(zhí)行情況解析
這篇文章主要為大家介紹了Java并發(fā)編程之LongAdder執(zhí)行情況解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04

