2014-03-25 23 views
11

前一段時間我發現了Scala Async Project。問題是:這個async塊中有什麼神奇的東西不能通過普通函數實現(沒有宏擴展)?Scala async vs. Java ForkJoinTask

讓我們看看從引進的第一個例子:

import ExecutionContext.Implicits.global 
import scala.async.Async.{async, await} 

val future = async { 
    val f1 = async { ...; true } 
    val f2 = async { ...; 42 } 
    if (await(f1)) await(f2) else 0 
} 

我沒有看到,不能用純Java編寫上面的例子什麼。此代碼完全一樣的東西:

import java.util.concurrent.*; 
import java.util.function.Supplier; 

// First define a helper method for creating async blocks: 
public static <T> ForkJoinTask<T> async(Supplier<T> supplier) { 
    return new RecursiveTask<T>() { 
     @Override 
     protected T compute() { 
      return supplier.get(); 
     } 
    }.fork(); 
} 

ForkJoinTask<Integer> future = ForkJoinPool.commonPool().submit(() -> { 
    ForkJoinTask<Boolean> f1 = async(() -> true); 
    ForkJoinTask<Integer> f2 = async(() -> 42); 

    if (f1.join()) { 
     return f2.join(); 
    } else { 
     return 42; 
    } 
}); 

什麼可以斯卡拉async做到這一點的Java不能?也許在一些更復雜的情況下?我錯過了什麼?

+4

我認爲Scala中的「任何事物」都可以重寫爲純Java的情況下..給予足夠的時間和精力: – user2864740

+1

僅供參考[它不直接回答Java部分,但無論如何](https://github.com/scala/async#comparison-with-direct-use-of-future-api) –

+1

@ user2864740以及任何用Java編寫的東西可以用純彙編重新實現:-) –

回答

9

您發佈的兩個代碼片段在工作方式下的工作方式有一個至關重要的區別:阻止操作

scala-async片段是大致等效於:

val future = { 
    val f1 = Future { ...; true } 
    val f2 = Future { ...; 42 } 
    f1.flatMap { b => 
    if(b) f2 else Future.successful(0) 
    } 
} 

這是一個基於回調的代碼。那裏沒有任何操作會阻塞任何線程。只有將來的包裝和回調註冊(在這種情況下,在flatMap的引擎下發生)。換句話說,在那裏一切都是異步

另一方面,來自Java的fork-join池join方法確實阻塞該線程。

沒有阻塞操作是一個重要的性能/可伸縮性優勢,因爲 - 極大地簡化 - 無阻塞=>需要的線程少>需要較少的OS資源+較少的上下文切換。

彙總:中scala-async的目的是使無阻塞,基於回調,異步處理,在其作爲標準語法自然,阻塞方法(就像你在Java中使用的一個)。

+0

我認爲'await'確實會阻止它被調用的線程。 – njzk2

+2

@ njzk2不,它並不是那種'scala-async'所具有的所有宏魔法的全部重點。 – ghik

+0

怎麼可能等不回答呢?即如何根據線程計算所述值尚未計算的值繼續執行? – njzk2