您好,登錄后才能下訂單哦!
在Java的線程執行中,不管是直接繼承Thread的方式,還是實現Runnable接口的方式,都不會獲取到線程執行的返回結果。這樣如果線程在執行過程中出現了錯誤,那么主線程也不會感知到。即使打印了日志,也不能立即拋出異常。事后查看日志才能發現出現了bug。而且到那時發生問題的代碼點距離真正的問題點可能會相差很遠。如果在線程池執行的過程中出現了bug能及時地拋出異常,那么這將會是一個很好的實現。解決上述問題的辦法是使用Callable接口,其可以獲取到線程的返回結果,通過Future的get方法來承接。以下通過一個1000個線程實現累加的例子,來演示Callable和Future的使用:
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 { //這里模擬一個耗時很長的操作 num.getAndIncrement(); //int a = 1 / 0; Thread.sleep(1); return null; } catch (Exception e) { return e.toString(); } finally { latch.countDown(); } }); } poolexecutor.shutdown(); //主線程等待所有分線程執行完畢后再執行 latch.await(); String errorMsg = submit.get(); //如果子線程在執行過程中有錯誤,則在此拋出該異常 if (errorMsg != null) { throw new RuntimeException(errorMsg); } System.out.println(num); } }
如果每個線程在執行的過程中沒出現問題,則返回的結果為null。如果返回結果不為null,則代表該線程執行的代碼有問題,此時將錯誤信息返回。放開上述第33行代碼的注釋,以此來模擬一個算術異常,再次執行上述代碼,可以得到如下的結果:
Exception in thread "main" java.lang.RuntimeException: java.lang.ArithmeticException: / by zero
at com.hys.test.Test.main(Test.java:49)
由上可以看到,在主線程拋出了算術異常,可以被感知到。
但是需要注意的一點的是,如果線程的執行結果互相依賴的話,也就是各線程都會調用Future的get方法的話,get方法不得不等待任務執行完成,換言之,如果多個任務提交后,返回的多個Future逐一調用get方法時,將會依次阻塞,任務的執行從并行變為串行。如果想解決該問題,可以考慮使用Java 8中的CompletableFuture來實現。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。