Java8中的簡易併發

Java8中的簡易併發 java

分享到: 5程序員



本文由 ImportNew - kingviker 翻譯自 jaxenter。歡迎加入Java小組。轉載請參見文章末尾的要求。多線程

有人曾經說過(很抱歉,咱們找不到原句了):併發


初級程序員認爲併發很難。spa

中級程序員認爲併發很簡單。線程

高級程序員認爲併發很難。翻譯

這說的很對。可是從好的方面來看,Java8爲咱們帶來了起色,經過lambda表達式和改進的API可使得編寫併發代碼更容易。讓咱們來具體的看看Java8的改進吧:對象


Java8對JDK 1.0 API的改進接口


java.lang.Thread早在JDK 1.0版本中就已經存在。在java8中被註解爲功能性接口的java.lang.Runnable也是。get


從如今起,幾乎不須要動大腦咱們就能夠提交Runnables給一個線程。讓咱們假設咱們有一個很耗時的操做:

public static int longOperation() {

    System.out.println("Running on thread #"

    + Thread.currentThread().getId());

 

    // [...]

    return 42;

}

咱們能夠用多種方法把這個操做傳遞給線程,例如:

Thread[] threads = {

  

    // Pass a lambda to a thread

    new Thread(() -> {

    longOperation();

    }),

  

    // Pass a method reference to a thread

    new Thread(ThreadGoodies::longOperation)

};

  

// Start all threads

Arrays.stream(threads).forEach(Thread::start);

  

// Join all threads

Arrays.stream(threads).forEach(t -> {

    try { t.join(); }

    catch (InterruptedException ignore) {}

});

就像咱們在以前的博文裏提到的同樣,lambda表達式沒有一個簡潔的方式來處理被檢查異常實在是一大憾事。在java.util.function包中新增的功能性接口都不會拋出被檢查異常,把這項工做留給了調用端。


在上一篇博文中,咱們已經所以而發佈了jOOλ(also jOOL,jOO-Lambda)包,該包包裝了JDK中的每個功能性接口,具備相同功能並且也容許拋出被檢異常。這在使用老的JDK API時特別有用,例如JDBC,或者上面提到的Thread API。使用jOOλ,咱們能夠這麼寫:


// Join all threads

Arrays.stream(threads).forEach(Unchecked.consumer(

    t -> t.join()

));

Java8中改進的Java5 API


Java的多線程功能一直沒有什麼轉機,直到Java5的ExecutorService的發佈。管理多線程是一個負擔,人們須要額外的庫或者一個J2EE/JEE容器來管理線程池。這些用Java5來處理已經容易了不少。咱們如今能夠提交一個Runnable對象或者一個Callable對象到ExcutorService,它管理本身的線程池。


下面是一個咱們如何在Java8中利用這些Java5的併發API的例子:

ExecutorService service = Executors

    .newFixedThreadPool(5);

  

Future[] answers = {

    service.submit(() -> longOperation()),

    service.submit(ThreadGoodies::longOperation)

};

  

Arrays.stream(answers).forEach(Unchecked.consumer(

    f -> System.out.println(f.get())

));

注意看,咱們是如何再次使用jOOλ中的UncheckedConsumer來包裝在運行期調用get()方法拋出的被檢異常。


Java8中的並行和ForkJoinPool


如今,Java8的Streams API在併發和並行方面有了很大改進。

在Java8中你能夠寫出以下的代碼:

Arrays.stream(new int[]{ 1, 2, 3, 4, 5, 6 })

  .parallel()

  .max()

  .ifPresent(System.out::println);

雖然在這個特殊的例子中不是很必要,但仍是挺有意思的,你僅僅調用了parallel()就運行IntStream.max()來啓用ForkJoinPool,而你沒必要擔憂包含的ForkJoinTasks。這是很是有用的,由於不是每一個人都可以接受JDK7中引進的複雜的JorkJoin API。

相關文章
相關標籤/搜索