Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么是新线程而不是未来{…}_Java_Multithreading_Scala_Blocking_Future - Fatal编程技术网

Java 为什么是新线程而不是未来{…}

Java 为什么是新线程而不是未来{…},java,multithreading,scala,blocking,future,Java,Multithreading,Scala,Blocking,Future,指示如何将java.util.concurrent.Future转换为scala.concurrent.Future,同时管理阻塞发生的位置: import java.util.concurrent.{Future=>JFuture} 导入scala.concurrent.{Future=>SFuture} val jfuture:jfuture[T]=??? val promise=promise[T]() 新线程( 新Runnable{ def run(){promise.complete(

指示如何将
java.util.concurrent.Future
转换为
scala.concurrent.Future
,同时管理阻塞发生的位置:

import java.util.concurrent.{Future=>JFuture}
导入scala.concurrent.{Future=>SFuture}
val jfuture:jfuture[T]=???
val promise=promise[T]()
新线程(
新Runnable{
def run(){promise.complete(尝试{jfuture.get})}
}
).开始
val future=promise.future
我的问题与评论中提出的问题相同:

future{jfuture.get}
有什么问题吗?为什么你用了一个额外的线程结合承诺

答复如下:

它会在你的拉线过程中挡住线。如果您已经为这种未来配置了ExecutionContext,则可以,但默认ExecutionContext包含的线程数量与处理器数量相同

我不确定我是否理解这个解释。重申:


future{jfuture.get}
有什么问题吗?在未来内部阻塞与手动创建新线程并在那里阻塞不一样吗?如果没有,又有什么不同呢?

其实很简单
scala.concurrent.Promise
未来
的具体实现,注定是异步计算

当您想要转换时,使用
jfuture.get
,您正在运行一个阻塞计算并输出一个立即解析的
scala.concurrent.Future

线程将阻塞,直到
jfuture
中的计算完成。
get
方法被阻塞

阻塞意味着在计算完成之前,
线程内不会发生任何其他事情。在间歇检查结果时,您实际上是在用类似于
的东西垄断
线程

while (!isDone() && !timeout) {
   // check if the computation is complete
}
具体而言:

val jfuture: JFuture[T] = ??? // some blocking task
当无法避免阻塞时,通常的做法是生成
新线程
新可运行线程
新可调用线程
,以允许计算执行/独占子线程

在@senia给出的示例中:

new Thread(new Runnable { def run() {
  promise.complete(Try{ jfuture.get })
}}).start
这与
future{jfuture.get}
有何不同?它不会阻止Scala提供的默认
ExecutionContext
,Scala的线程数与机器处理器的线程数相同


这意味着代码中的所有其他未来都必须等待
future{jfuture.get}
完成,因为整个上下文都被阻止。

future{jfuture.get}
future{future{jfuture.get}
之间几乎没有区别

val format = new java.text.SimpleDateFormat("HH:mm:ss").format(_: Date)

val startTime = new Date
(1 to 8) map {_ => future{ Thread.sleep(10000) }}
future{
  2+2
  println(s"2+2 done. Start time: ${format(startTime)}, end time: ${format(new Date)}")
}

// 2+2 done. Start time: 20:48:18, end time: 20:48:28
默认线程池中的线程数量与处理器数量相同

使用
jfuture.get
将阻塞1个线程

假设您有8个处理器。另外,我们假设每个
jfuture.get
需要10秒。现在创建8
future{jfuture.get}

val format = new java.text.SimpleDateFormat("HH:mm:ss").format(_: Date)

val startTime = new Date
(1 to 8) map {_ => future{ Thread.sleep(10000) }}
future{
  2+2
  println(s"2+2 done. Start time: ${format(startTime)}, end time: ${format(new Date)}")
}

// 2+2 done. Start time: 20:48:18, end time: 20:48:28
10秒对于
2+2
评估来说有点太长了

同一执行上下文中的所有其他
future
s和所有参与者将停止10秒

使用其他执行上下文:

object BlockingExecution {
  val executor = ExecutionContext.fromExecutor(new ForkJoinPool(20))
}

def blockingFuture[T](f: => T) = {
  future( f )(BlockingExecution.executor)
}

val startTime = new Date
(1 to 8) map {_ => blockingFuture{ Thread.sleep(10000) }}
future{
  2+2
  println(s"2+2 done. Start time: ${format(startTime)}, end time: ${format(new Date)}")
}

// 2+2 done. Start time: 21:26:18, end time: 21:26:18

您可以使用
new Thread(new Runnable{…
)实现
blockingFuture
,但是额外的执行上下文允许您限制线程数。

您到底不明白什么?线程阻塞意味着什么?@AlexeiKaigorodov我稍微修改了我的问题:
future{jfuture.get}
?在未来内部阻止与手动创建新线程并在那里阻止不一样吗?如果不一样,有什么区别?是的,在未来内部阻止与手动创建新线程并在那里阻止一样糟糕。转换为
scala.concurrent.future
的想法是通过使用
onComplete
来避免完全阻止我的印象是,生成一个新线程并在其中执行
somethingtatblocks()
与将来(somethingtatblocks())是一样的。我的问题主要是关于这是否是真的,如果不是,又有什么不同?因此,一般来说,不建议在具有默认执行上下文的将来进行长时间的计算?@DominykasMostauskis:不,默认执行上下文有一个线程池,并选择其中一个线程池在将来运行代码。它不跨新线程因为创建线程是一个昂贵的操作,线程是一个有限的资源。没有内在的原因,计算2+2的未来需要在其他未来之后执行。(您只要求异步计算9件事情。)如果您更改
future{thread.sleep(10000)}
to
Future{blocking{Thread.sleep(10000)}
,2+2未来将立即执行。我的理解是,
阻塞
方法给出了一个提示,线程池将首先处理其他未来。我还没有找到任何好的资源来准确描述这里发生了什么。@Patrick这是真的。当使用
阻塞
时,全局线程池将为该计算创建一个新线程,这样它就不会耗尽线程。更多信息请参见“阻塞”部分