轻量级的 Scala fork join 语法
尽管即将推出 java 7 标准 fork/join 框架,但我正在构建一些语法轻量级的辅助方法,以便客户端并行运行代码。 这是一个可运行的 main 方法来说明这个想法。
import actors.Futures
object ForkTest2 {
def main(args: Array[String]) {
test1
test2
}
def test1 {
val (a, b, c) =fork({
Thread.sleep(500)
println("inside fx1 ",+System.currentTimeMillis)
true
}, {
Thread.sleep(1000)
println("inside fx2 ",+System.currentTimeMillis)
"stringResult"
}, {
Thread.sleep(1500)
println("inside fx3 ",+System.currentTimeMillis)
1
})
println(b, a, c)
true
}
def test2 {
val results = forkAll({
() =>
Thread.sleep(500)
println("inside fx1 ",+System.currentTimeMillis)
true
}, {
() =>
Thread.sleep(1000)
println("inside fx2 ",+System.currentTimeMillis)
"stringResult"
}, {
() =>
Thread.sleep(1500)
println("inside fx3 ",+System.currentTimeMillis)
1
}, {
() =>
Thread.sleep(2000)
println("inside fx4 ",+System.currentTimeMillis)
1.023
})
println(results)
true
}
val tenMinutes = 1000 * 60 * 10
def fork[A, B, C](
fx1: => A,
fx2: => B,
fx3: => C
) = {
val re1 = Futures.future(fx1)
val re2 = Futures.future(fx2)
val re3 = Futures.future(fx3)
//default wait 10 minutes
val result = Futures.awaitAll(tenMinutes, re1, re2, re3)
(
result(0).asInstanceOf[Option[A]],
result(1).asInstanceOf[Option[B]],
result(2).asInstanceOf[Option[C]]
)
}
type fxAny = () => Any
def forkAll(
fx1: fxAny*
): List[Any] = {
val results = fx1.toList.map {fx: fxAny => Futures.future(fx())}
Futures.awaitAll(tenMinutes, results: _*)
}
}
示例输出是
(inside fx1 ,1263804802301)
(inside fx2 ,1263804802801)
(inside fx3 ,1263804803301)
(Some(stringResult),Some(true),Some(1))
(inside fx1 ,1263804803818)
(inside fx2 ,1263804804318)
(inside fx3 ,1263804804818)
(inside fx4 ,1263804805318)
List(Some(true), Some(stringResult), Some(1), Some(1.023))
test 1 说明类型安全返回类型
test 2 说明任意输入参数
我希望将这两种测试方法结合起来,以便客户端代码可以与类型安全返回类型并行运行任意函数。
关于任意函数参数的另一点是:
我认为该行
type fxAny = () => Any
确实应该编码为
type fxAny = => Any
,但 scala 编译器不允许我这样做。
任何帮助都是值得赞赏的。
Despite the upcoming java 7 standard fork/join framework, I am building some helper method that is light weight in syntax for client to run code in parallel.
Here is a runnable main method to illustrate the idea.
import actors.Futures
object ForkTest2 {
def main(args: Array[String]) {
test1
test2
}
def test1 {
val (a, b, c) =fork({
Thread.sleep(500)
println("inside fx1 ",+System.currentTimeMillis)
true
}, {
Thread.sleep(1000)
println("inside fx2 ",+System.currentTimeMillis)
"stringResult"
}, {
Thread.sleep(1500)
println("inside fx3 ",+System.currentTimeMillis)
1
})
println(b, a, c)
true
}
def test2 {
val results = forkAll({
() =>
Thread.sleep(500)
println("inside fx1 ",+System.currentTimeMillis)
true
}, {
() =>
Thread.sleep(1000)
println("inside fx2 ",+System.currentTimeMillis)
"stringResult"
}, {
() =>
Thread.sleep(1500)
println("inside fx3 ",+System.currentTimeMillis)
1
}, {
() =>
Thread.sleep(2000)
println("inside fx4 ",+System.currentTimeMillis)
1.023
})
println(results)
true
}
val tenMinutes = 1000 * 60 * 10
def fork[A, B, C](
fx1: => A,
fx2: => B,
fx3: => C
) = {
val re1 = Futures.future(fx1)
val re2 = Futures.future(fx2)
val re3 = Futures.future(fx3)
//default wait 10 minutes
val result = Futures.awaitAll(tenMinutes, re1, re2, re3)
(
result(0).asInstanceOf[Option[A]],
result(1).asInstanceOf[Option[B]],
result(2).asInstanceOf[Option[C]]
)
}
type fxAny = () => Any
def forkAll(
fx1: fxAny*
): List[Any] = {
val results = fx1.toList.map {fx: fxAny => Futures.future(fx())}
Futures.awaitAll(tenMinutes, results: _*)
}
}
a sample out put is
(inside fx1 ,1263804802301)
(inside fx2 ,1263804802801)
(inside fx3 ,1263804803301)
(Some(stringResult),Some(true),Some(1))
(inside fx1 ,1263804803818)
(inside fx2 ,1263804804318)
(inside fx3 ,1263804804818)
(inside fx4 ,1263804805318)
List(Some(true), Some(stringResult), Some(1), Some(1.023))
test 1 illustrate a type safe return type
test 2 illustrate a arbitrary input argument
I hope to combine the two test method so the client code can run arbitrary function in parallel with type safe return type.
Another point about the arbitrary function arguments is:
I think the line
type fxAny = () => Any
should really be code as
type fxAny = => Any
, but the scala compiler do not allow me to do so.
Any help is appreciate.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Eric Torreborre 在 @retronym 提供的链接中写道:
这是您的测试的 LazyParameter 版本:
...
编辑:正如您所注意到的,隐式评估按名称参数,并且不会继续下去评估延迟。为什么不直接使用“未来”这个词呢?我个人认为这使代码更具可读性。
……
Eric Torreborre wrote in the link provided by @retronym:
Here's LazyParameter version of your test:
...
Edit: As you've noticed, implicit evaluates the by-name parameter and it doesn't carry forward the evaluation delay. Why not just use the word
future
? I personally think it makes the code more readable....
...
由于以下错误,您不能使用按名称调用类型作为重复参数(也称为可变参数): https://lampsvn.epfl.ch/trac/scala/ticket/237
请参阅此处最近的讨论:http://old.nabble.com/Lazy-varargs-td27169264.html
You can't use call-by-name types as a repeated parameter (aka varargs), thanks to this bug: https://lampsvn.epfl.ch/trac/scala/ticket/237
See recent discussion here: http://old.nabble.com/Lazy-varargs-td27169264.html
任何感兴趣的人的示例实现,
对于带有几个函数参数的用例,可能只是定义具有不同数量参数的 fork 函数列表(遵循元组定义中的想法)
并享受类型安全返回类型
A sample implementation for anyone interested,
For use case that with a few function argument, may be just define list of fork function with different number of arguments (following the idea in tuple definition)
and enjoy type safe return type