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。