Java8多线程ForkJoinPool:处理异常
引入Java8 lambda背后的主要動機之一是能夠盡可能輕松地使用多核的能力(請參閱精通Lambdas:多核世界中的Java編程 )。 只需將代碼從collection.stream()...更改為collection.parallelStream()...您就可以使用即時多線程,從而為您的計算機帶來所有CPU功能。 (在這一點上,讓我們忽略爭用。)
如果打印出parallelStream所使用的線程的名稱,您會注意到它們與ForkJoin框架所使用的線程相同,如下所示:
請參閱本杰明·溫特伯格的博客 ,以獲取一個很好的示例。
現在,在Java 8中,您可以將這個commonPool與ForkJoinPool commonPool()上的新方法直接一起使用。 這將返回帶有commonPool線程的ForkJoinPool(這是一個ExecutorService)實例–與parallelStream中使用的線程相同。 這意味著您直接使用commonPool進行的任何工作都可以與parallelStream中完成的工作很好地配合,尤其是線程調度和線程之間的竊取。
讓我們來看一個如何使用ForkJoin的示例,尤其是在處理棘手的異常主題時。
首先,通過調用ForkJoin.commonPool()獲得commonPool的實例。 您可以使用submit()方法向其提交任務。 因為我們使用的是Java8,所以我們可以傳入lambda表達式,這確實很不錯。 與所有ExecutorService實現一樣,您可以將Runnable或Callable實例傳遞給Runnable submit() 。 當您將lambda傳遞給Submit方法時,它將通過檢查方法簽名將其自動轉換為Runnable或Callable 。
這導致一個有趣的問題,突出了lambda如何工作。 假設您有一個返回類型為void的方法(如Runnable),但拋出了一個已檢查的異常(如Callable)。 參見方法throwException()
在下面的代碼清單中可以找到這樣的例子。 如果您編寫此代碼,它將無法編譯。
這樣做的原因是,由于void返回類型,編譯器假定您正在嘗試創建Runnable。 當然,Runnable不能拋出異常。 要解決此問題,您需要強制編譯器了解您正在創建一個Callable,使用此代碼技巧可以允許拋出Exception。
Future task1 = commonPool.submit(() -> {throwException("task 1");return null;});這有點混亂,但可以完成工作。 可以說,編譯器本來可以解決這個問題。
下面的完整代碼清單中還有兩點要強調。 第一,您可以使用commonPool.getParallelism()看到池中有多少個線程可用。 可以使用參數'-Djava.util.concurrent.ForkJoinPool.common.parallelism'進行調整。 第二,注意如何解開ExecutionException,以便您的代碼僅向其調用者顯示IOException,而不是非特定的ExecutionException。 另請注意,此代碼在第一個異常時失敗。 如果要收集所有異常,則必須適當地構造代碼,可能會返回異常列表。 或者更巧妙地拋出一個包含基礎異常列表的自定義異常。
public class ForkJoinTest {public void run() throws IOException{ForkJoinPool commonPool = ForkJoinPool.commonPool();Future task1 = commonPool.submit(() -> {throwException("task 1");return null;});Future task2 = commonPool.submit(() -> {throwException("task 2");return null;});System.out.println("Do something while tasks being " +"executed on " + commonPool.getParallelism()+ " threads");try {//wait on the result from task2task2.get();//wait on the result from task1task1.get();} catch (InterruptedException e) {throw new AssertionError(e);} catch (ExecutionException e) {Throwable innerException = e.getCause();if (innerException instanceof RuntimeException) {innerException = innerException.getCause();if(innerException instanceof IOException){throw (IOException) innerException;}}throw new AssertionError(e);}}public void throwException(String message) throws IOException,InterruptedException {Thread.sleep(100);System.out.println(Thread.currentThread() + " throwing IOException");throw new IOException("Throw exception for " + message);}public static void main(String[] args) throws IOException{new ForkJoinTest().run();} }翻譯自: https://www.javacodegeeks.com/2015/02/java8-multi-threading-forkjoinpool-dealing-with-exceptions.html
總結
以上是生活随笔為你收集整理的Java8多线程ForkJoinPool:处理异常的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用JAX-RS和Jetty创建Web服
- 下一篇: 电脑涂色软件(涂色软件推荐)