Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.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
如何获得scala';What’与tailrec合作有什么困难?_Scala_Java.util.concurrent - Fatal编程技术网

如何获得scala';What’与tailrec合作有什么困难?

如何获得scala';What’与tailrec合作有什么困难?,scala,java.util.concurrent,Scala,Java.util.concurrent,我正在为Futures编写scala java互操作包装器,但我不知道实现scala.concurrent.Future.onComplete()的正确方法。这可能有效: def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = { executor.execute(new Runnable { @tailrec def run = value match {

我正在为Futures编写scala java互操作包装器,但我不知道实现scala.concurrent.Future.onComplete()的正确方法。这可能有效:

def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
  executor.execute(new Runnable {
    @tailrec
    def run = value match {
      case Some(t) => func(t)
      case None => { Thread.sleep(100); run }
    }
  })
}
但是建议当我必须阻塞时,我应该将代码的相关部分传递给scala.concurrent.blocking,让ExecutionContext知道发生了什么。问题是,当我用阻塞{}包围值匹配{…}时,它不再是尾部调用

众所周知的正确方法是什么

编辑:为了完整起见,这里是整个包装类:

class JavaFutureWrapper[T](val jf: java.util.concurrent.Future[T]) extends scala.concurrent.Future[T] {
  def isCompleted = jf.isDone

  def result(atMost: Duration)(implicit permit: CanAwait): T =
    atMost match { case Duration(timeout, units) => jf.get(timeout, units) }

  def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
    executor.execute(new Runnable {
      @tailrec
      def run = value match {
        case Some(t) => func(t)
        case None => { Thread.sleep(100); run }
      }
    })
  }

  def ready(atMost: Duration)(implicit permit: CanAwait): this.type = atMost match {
    case Duration(timeout, units) => {
      jf.get(timeout, units)
      this
    }
  }

  def value: Option[Try[T]] = (jf.isCancelled, jf.isDone) match {
    case (true, _) => Some(Failure(new Exception("Execution was cancelled!")))
    case (_, true) => Some(Success(jf.get))
    case _ => None
  }
}

我只想等待Java未来的完成:

import scala.util.{Try, Success, Failure}
import scala.concurrent._
import java.util.concurrent.TimeUnit

class JavaFutureWrapper[T](val jf: java.util.concurrent.Future[T])
  extends scala.concurrent.Future[T] {
  ...

  def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit =
    executor.execute(new Runnable {
      def run: Unit = {
        val result = Try(blocking(jf.get(Long.MaxValue, TimeUnit.MILLISECONDS)))
        func(result)
      }
    })
  ...
}

嗯,我对0的答案的编辑没有得到批准,因此为了未来读者的利益,我将采用以下解决方案(从0简化而来)


你能指出什么是JavaAPI吗?例如,
value
从何而来?你为什么要让线程休眠100毫秒?换句话说,潜在的阻塞代码在哪里?我已经为您粘贴了整个包装类。睡眠是为了防止在我调查java未来是否已经完成时出现紧循环。整个run方法将被阻塞,直到jf决定它是完成还是取消。如果只在Thread.sleep()周围加上阻塞会怎么样?另一个想法是使用一段时间而不是递归调用。哦,天哪,我没有想到只围绕睡眠,我想我们可能会有一个赢家。ExecutionContext应该足够聪明,能够处理快速从阻塞区出来然后又回到阻塞区,对吗?哦,对,是的,这显然是正确的答案,谢谢!我已经给你发了一个编辑,它简化了代码,一旦输入,我会把这个标记为答案。编辑改变了意思。在执行
func
的周围放置
阻塞
。但是
func
有责任声明它是否正在执行阻止的操作。所以我认为这个版本是正确的,只在等待
jf
完成时阻塞。好的一点,这里有另一个版本的编辑没有这个问题是的,
。没有超时的get
似乎无限期地等待。无限期地等待,而不是大约3亿年?是的,不知怎的,我对这种交易没意见。另外,如果在3亿年后,未来还没有到来,我希望onComplete不会表示完成。
def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
  executor.execute(new Runnable {
    def run = func(Try( blocking { jf.get } ))
  })
}