在Java的線程執(zhí)行中,不管是直接繼承Thread的方式,還是實(shí)現(xiàn)Runnable接口的方式,都不會(huì)獲取到線程執(zhí)行的返回結(jié)果。這樣如果線程在執(zhí)行過(guò)程中出現(xiàn)了錯(cuò)誤,那么主線程也不會(huì)感知到。即使打印了日志,也不能立即拋出異常。事后查看日志才能發(fā)現(xiàn)出現(xiàn)了bug。而且到那時(shí)發(fā)生問(wèn)題的代碼點(diǎn)距離真正的問(wèn)題點(diǎn)可能會(huì)相差很遠(yuǎn)。如果在線程池執(zhí)行的過(guò)程中出現(xiàn)了bug能及時(shí)地拋出異常,那么這將會(huì)是一個(gè)很好的實(shí)現(xiàn)。解決上述問(wèn)題的辦法是使用Callable接口,其可以獲取到線程的返回結(jié)果,通過(guò)Future的get方法來(lái)承接。以下通過(guò)一個(gè)1000個(gè)線程實(shí)現(xiàn)累加的例子,來(lái)演示Callable和Future的使用:

創(chuàng)新互聯(lián)建站為客戶提供專業(yè)的成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、程序、域名、空間一條龍服務(wù),提供基于WEB的系統(tǒng)開發(fā). 服務(wù)項(xiàng)目涵蓋了網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站程序開發(fā)、WEB系統(tǒng)開發(fā)、微信二次開發(fā)、移動(dòng)網(wǎng)站建設(shè)等網(wǎng)站方面業(yè)務(wù)。
package com.hys.test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
public class Test {
private static AtomicInteger num = new AtomicInteger();
public static void main(String[] args) throws InterruptedException, ExecutionException {
CountDownLatch latch = new CountDownLatch(1000);
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("increment-pool-%d").build();
ExecutorService poolexecutor = new ThreadPoolExecutor(1000, 1000, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
Future<String> submit = null;
for (int i = 0; i < 1000; i++) {
if (submit != null && submit.get() != null) {
latch.countDown();
continue;
}
submit = poolexecutor.submit(() -> {
try {
//這里模擬一個(gè)耗時(shí)很長(zhǎng)的操作
num.getAndIncrement();
//int a = 1 / 0;
Thread.sleep(1);
return null;
} catch (Exception e) {
return e.toString();
} finally {
latch.countDown();
}
});
}
poolexecutor.shutdown();
//主線程等待所有分線程執(zhí)行完畢后再執(zhí)行
latch.await();
String errorMsg = submit.get();
//如果子線程在執(zhí)行過(guò)程中有錯(cuò)誤,則在此拋出該異常
if (errorMsg != null) {
throw new RuntimeException(errorMsg);
}
System.out.println(num);
}
}如果每個(gè)線程在執(zhí)行的過(guò)程中沒(méi)出現(xiàn)問(wèn)題,則返回的結(jié)果為null。如果返回結(jié)果不為null,則代表該線程執(zhí)行的代碼有問(wèn)題,此時(shí)將錯(cuò)誤信息返回。放開上述第33行代碼的注釋,以此來(lái)模擬一個(gè)算術(shù)異常,再次執(zhí)行上述代碼,可以得到如下的結(jié)果:
Exception in thread "main" java.lang.RuntimeException: java.lang.ArithmeticException: / by zero
at com.hys.test.Test.main(Test.java:49)
由上可以看到,在主線程拋出了算術(shù)異常,可以被感知到。
但是需要注意的一點(diǎn)的是,如果線程的執(zhí)行結(jié)果互相依賴的話,也就是各線程都會(huì)調(diào)用Future的get方法的話,get方法不得不等待任務(wù)執(zhí)行完成,換言之,如果多個(gè)任務(wù)提交后,返回的多個(gè)Future逐一調(diào)用get方法時(shí),將會(huì)依次阻塞,任務(wù)的執(zhí)行從并行變?yōu)榇小H绻虢鉀Q該問(wèn)題,可以考慮使用Java 8中的CompletableFuture來(lái)實(shí)現(xiàn)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
名稱欄目:java通過(guò)Callable和Future來(lái)接收線程池的執(zhí)行結(jié)果
轉(zhuǎn)載來(lái)源:http://www.chinadenli.net/article16/iiigdg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、定制網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、小程序開發(fā)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)