복붙노트

[SCALA] 스칼라 선물 - 시간 제한에 내장?

SCALA

스칼라 선물 - 시간 제한에 내장?

내가 정확히 공식 튜토리얼 심판에서 이해하지 못하는 선물의 측면이있다. http://docs.scala-lang.org/overviews/core/futures.html

스칼라의 선물은 어떤 종류의 타임 아웃 메커니즘의 구축이 있습니까? "Implicits.global"의 암시 적 범위는 결국 onFailure이 비 블로킹 방식으로 발광 할 않는 ...의는 예를 아래에 5 기가 바이트 텍스트 파일이었다 가정 해 봅시다 또는 정의 할 수 있습니까? 그리고 어떤 종류의 기본 시간 제한없이, 즉도 성공이나 실패는 지금까지 발사 할 가능성을 의미하지 않을까요?

import scala.concurrent._
import ExecutionContext.Implicits.global

val firstOccurence: Future[Int] = future {
  val source = scala.io.Source.fromFile("myText.txt")
  source.toSeq.indexOfSlice("myKeyword")
}
firstOccurence onSuccess {
  case idx => println("The keyword first appears at position: " + idx)
}
firstOccurence onFailure {
  case t => println("Could not process file: " + t.getMessage)
}

해결법

  1. ==============================

    1.당신은 당신이 미래의 결과를 얻을 차단 사용하십시오 시간 제한 동작을 얻을. 당신이 비 블로킹 콜백 onComplete를,는 onSuccess 또는 onFailure를 사용하려는 경우, 당신은 당신의 자신의 타임 아웃 처리를 롤백해야합니다. Akka 배우 사이의 요청 / 응답 (?) 메시지에 대한 처리 시간 제한에 내장,하지만 당신은 Akka를 사용하여 시작하려는 경우하지 않도록하고있다. FWIW는, Akka에서, 타임 아웃 처리를 위해, 그들은 Future.firstCompletedOf, 실제 비동기 작업을 나타내는 하나는 타임 아웃을 나타내는 하나를 통해 두 개의 선물을 구성한다. (A HashedWheelTimer를 통해) 타임 아웃 타이머가 처음 나올 경우 비동기 콜백에 실패를 얻을.

    당신은 당신이 미래의 결과를 얻을 차단 사용하십시오 시간 제한 동작을 얻을. 당신이 비 블로킹 콜백 onComplete를,는 onSuccess 또는 onFailure를 사용하려는 경우, 당신은 당신의 자신의 타임 아웃 처리를 롤백해야합니다. Akka 배우 사이의 요청 / 응답 (?) 메시지에 대한 처리 시간 제한에 내장,하지만 당신은 Akka를 사용하여 시작하려는 경우하지 않도록하고있다. FWIW는, Akka에서, 타임 아웃 처리를 위해, 그들은 Future.firstCompletedOf, 실제 비동기 작업을 나타내는 하나는 타임 아웃을 나타내는 하나를 통해 두 개의 선물을 구성한다. (A HashedWheelTimer를 통해) 타임 아웃 타이머가 처음 나올 경우 비동기 콜백에 실패를 얻을.

    자신의 압연의 아주 간단한 예는 다음과 같이 갈 수 있습니다. 일정 시간 초과에 대한 우선 대상 :

    import org.jboss.netty.util.{HashedWheelTimer, TimerTask, Timeout}
    import java.util.concurrent.TimeUnit
    import scala.concurrent.duration.Duration
    import scala.concurrent.Promise
    import java.util.concurrent.TimeoutException
    
    object TimeoutScheduler{
      val timer = new HashedWheelTimer(10, TimeUnit.MILLISECONDS)
      def scheduleTimeout(promise:Promise[_], after:Duration) = {
        timer.newTimeout(new TimerTask{
          def run(timeout:Timeout){              
            promise.failure(new TimeoutException("Operation timed out after " + after.toMillis + " millis"))        
          }
        }, after.toNanos, TimeUnit.NANOSECONDS)
      }
    }
    

    그런 다음 함수는 미래를 가지고 거기에 시간 제한 동작을 추가합니다 :

    import scala.concurrent.{Future, ExecutionContext, Promise}
    import scala.concurrent.duration.Duration
    
    def withTimeout[T](fut:Future[T])(implicit ec:ExecutionContext, after:Duration) = {
      val prom = Promise[T]()
      val timeout = TimeoutScheduler.scheduleTimeout(prom, after)
      val combinedFut = Future.firstCompletedOf(List(fut, prom.future))
      fut onComplete{case result => timeout.cancel()}
      combinedFut
    }
    

    내가 여기에 사용하고있는 HashedWheelTimer가의 Netty에서 유의하십시오.

  2. ==============================

    2.난 그냥 동료에 대한 TimeoutFuture 클래스를 만들었습니다 :

    난 그냥 동료에 대한 TimeoutFuture 클래스를 만들었습니다 :

    package model
    
    import scala.concurrent._
    import scala.concurrent.duration._
    import play.libs.Akka
    import play.api.libs.concurrent.Execution.Implicits._
    
    object TimeoutFuture {
      def apply[A](timeout: FiniteDuration)(block: => A): Future[A] = {
    
        val prom = promise[A]
    
        // timeout logic
        Akka.system.scheduler.scheduleOnce(timeout) {
          prom tryFailure new java.util.concurrent.TimeoutException
        }
    
        // business logic
        Future { 
          prom success block
        }
    
        prom.future
      } 
    }
    
    val future = TimeoutFuture(10 seconds) { 
      // do stuff here
    }
    
    future onComplete {
      case Success(stuff) => // use "stuff"
      case Failure(exception) => // catch exception (either TimeoutException or an exception inside the given block)
    }
    
  3. ==============================

    3.이 답변의 모든 추가 종속성을 필요로한다. 나는 시간 제한을 실행하는 데이 경우, 미래의 기능을 실행할 수있는 효율적인 방법입니다 java.util.Timer를 사용하여 버전을 쓰기로했다.

    이 답변의 모든 추가 종속성을 필요로한다. 나는 시간 제한을 실행하는 데이 경우, 미래의 기능을 실행할 수있는 효율적인 방법입니다 java.util.Timer를 사용하여 버전을 쓰기로했다.

    여기에 자세한 내용과 블로그 게시물

    다음과 같이 스칼라의 약속이 사용하여, 우리는 시간 제한이있는 미래를 만들 수 있습니다 :

    package justinhj.concurrency
    
    import java.util.concurrent.TimeoutException
    import java.util.{Timer, TimerTask}
    
    import scala.concurrent.duration.FiniteDuration
    import scala.concurrent.{ExecutionContext, Future, Promise}
    import scala.language.postfixOps
    
    object FutureUtil {
    
      // All Future's that use futureWithTimeout will use the same Timer object
      // it is thread safe and scales to thousands of active timers
      // The true parameter ensures that timeout timers are daemon threads and do not stop
      // the program from shutting down
    
      val timer: Timer = new Timer(true)
    
      /**
        * Returns the result of the provided future within the given time or a timeout exception, whichever is first
        * This uses Java Timer which runs a single thread to handle all futureWithTimeouts and does not block like a
        * Thread.sleep would
        * @param future Caller passes a future to execute
        * @param timeout Time before we return a Timeout exception instead of future's outcome
        * @return Future[T]
        */
      def futureWithTimeout[T](future : Future[T], timeout : FiniteDuration)(implicit ec: ExecutionContext): Future[T] = {
    
        // Promise will be fulfilled with either the callers Future or the timer task if it times out
        val p = Promise[T]
    
        // and a Timer task to handle timing out
    
        val timerTask = new TimerTask() {
          def run() : Unit = {
                p.tryFailure(new TimeoutException())
            }
          }
    
        // Set the timeout to check in the future
        timer.schedule(timerTask, timeout.toMillis)
    
        future.map {
          a =>
            if(p.trySuccess(a)) {
              timerTask.cancel()
            }
        }
        .recover {
          case e: Exception =>
            if(p.tryFailure(e)) {
              timerTask.cancel()
            }
        }
    
        p.future
      }
    
    }
    
  4. ==============================

    4.당신은 다음과 같이 코드를 작성할 수 있도록 플레이 프레임 워크는 Promise.timeout을 포함

    당신은 다음과 같이 코드를 작성할 수 있도록 플레이 프레임 워크는 Promise.timeout을 포함

    private def get(): Future[Option[Boolean]] = {
      val timeoutFuture = Promise.timeout(None, Duration("1s"))
      val mayBeHaveData = Future{
        // do something
        Some(true)
      }
    
      // if timeout occurred then None will be result of method
      Future.firstCompletedOf(List(mayBeHaveData, timeoutFuture))
    }
    
  5. ==============================

    5.당신이 미래를 기다릴 때 시간 제한을 지정할 수 있습니다 :

    당신이 미래를 기다릴 때 시간 제한을 지정할 수 있습니다 :

    scala.concurrent.Future를 들어, 결과 방법을 사용하면 타임 아웃을 지정할 수 있습니다.

    scala.actors.Future를 들어, Futures.awaitAll는 타임 아웃을 지정할 수 있습니다.

    나는 붙박이 미래의 실행 시간 제한이 있다고 생각하지 않습니다.

  6. ==============================

    6.나는 이것이 스칼라 표준없는 매우 놀라운 일입니다. 내 버전은 짧고 종속성이 없습니다

    나는 이것이 스칼라 표준없는 매우 놀라운 일입니다. 내 버전은 짧고 종속성이 없습니다

    import scala.concurrent.Future
    
    sealed class TimeoutException extends RuntimeException
    
    object FutureTimeout {
    
      import scala.concurrent.ExecutionContext.Implicits.global
    
      implicit class FutureTimeoutLike[T](f: Future[T]) {
        def withTimeout(ms: Long): Future[T] = Future.firstCompletedOf(List(f, Future {
          Thread.sleep(ms)
          throw new TimeoutException
        }))
    
        lazy val withTimeout: Future[T] = withTimeout(2000) // default 2s timeout
      }
    
    }
    

    사용 예

    import FutureTimeout._
    Future { /* do smth */ } withTimeout
    
  7. ==============================

    7.아무도 아직 akka 스트림을 언급하지입니다. 흐름은 쉽게 completionTimeout 방법이 있고, 단일 소스 스트림에 그 적용하는 것은 미래처럼 작동합니다.

    아무도 아직 akka 스트림을 언급하지입니다. 흐름은 쉽게 completionTimeout 방법이 있고, 단일 소스 스트림에 그 적용하는 것은 미래처럼 작동합니다.

    실제로 실행 소스를 종료 할 수 있도록하지만, akka 스트림도, 즉 그것은 자원으로 타임 아웃 신호를 제거한다.

  8. ==============================

    8.당신은 시간 제한 논리를 제어하는 ​​하나가 작가에게 (약속 홀더를) 원하는 경우, 다음과 같은 방법으로, akka.pattern.after 사용

    당신은 시간 제한 논리를 제어하는 ​​하나가 작가에게 (약속 홀더를) 원하는 경우, 다음과 같은 방법으로, akka.pattern.after 사용

    val timeout = akka.pattern.after(10 seconds, system.scheduler)(Future.failed(new TimeoutException(s"timed out during...")))
    Future.firstCompletedOf(Seq(promiseRef.future, timeout))
    

    약속 완료 로직이 발생하지 않을 경우이 방법은, 발신자의 미래는 여전히 실패와 어떤 점에서 완료됩니다.

  9. ==============================

    9.Monix 작업은 시간 제한 지원을하고있다

    Monix 작업은 시간 제한 지원을하고있다

    import monix.execution.Scheduler.Implicits.global
    import monix.eval._
    import scala.concurrent.duration._
    import scala.concurrent.TimeoutException
    
    val source = Task("Hello!").delayExecution(10.seconds)
    
    // Triggers error if the source does not complete in 3 seconds after runOnComplete
    val timedOut = source.timeout(3.seconds)
    
    timedOut.runOnComplete(r => println(r))
    //=> Failure(TimeoutException)
    
  10. ==============================

    10.나는 Akka 시스템 디스패처를 사용 (위의 플레이 예 기준)이 버전을 사용하고 있습니다 :

    나는 Akka 시스템 디스패처를 사용 (위의 플레이 예 기준)이 버전을 사용하고 있습니다 :

    object TimeoutFuture {
      def apply[A](system: ActorSystem, timeout: FiniteDuration)(block: => A): Future[A] = {
        implicit val executionContext = system.dispatcher
    
        val prom = Promise[A]
    
        // timeout logic
        system.scheduler.scheduleOnce(timeout) {
          prom tryFailure new java.util.concurrent.TimeoutException
        }
    
        // business logic
        Future {
          try {
            prom success block
          } catch {
            case t: Throwable => prom tryFailure t
          }
        }
    
        prom.future
      }
    }
    
  11. ==============================

    11.미래 IMO에 제한 시간을 지정하는 가장 간단한 방법은 스칼라의 미래는 더 이상 지정된 제한 시간보다 오래 걸리는 경우는 TimeoutException를 슬로우합니다 scala.concurrent.Await.ready를 사용하여 장치에 내장되어 있습니다. 그렇지 않으면 미래 자체를 반환합니다. 다음은 간단한 예는 인위적인

    미래 IMO에 제한 시간을 지정하는 가장 간단한 방법은 스칼라의 미래는 더 이상 지정된 제한 시간보다 오래 걸리는 경우는 TimeoutException를 슬로우합니다 scala.concurrent.Await.ready를 사용하여 장치에 내장되어 있습니다. 그렇지 않으면 미래 자체를 반환합니다. 다음은 간단한 예는 인위적인

    import scala.concurrent.ExecutionContext.Implicits._
    import scala.concurrent.duration._
    val f1: Future[Int] = Future {
      Thread.sleep(1100)
      5
    }
    
    val fDoesntTimeout: Future[Int] = Await.ready(f1, 2000 milliseconds)
    
    val f: Future[Int] = Future {
      Thread.sleep(1100)
      5
    }
    val fTimesOut: Future[Int] = Await.ready(f, 100 milliseconds)
    
  12. ==============================

    12.당신은 기다리고 있습니다를 이용하여 마무리에 미래를 기다릴 수 있습니다.

    당신은 기다리고 있습니다를 이용하여 마무리에 미래를 기다릴 수 있습니다.

    import scala.concurrent.duration._
    import scala.concurrent.{Await, Future}
    
    val meaningOfLife: Int = Await.result(Future(42), 1.nano)
    println (meaningOfLife)
    

    상기 인쇄물 (42)

    당신은이 경우에 사용할 수있는 암시의 ExecutionContext를해야 할 수도 있습니다, 단지 추가 :

    import scala.concurrent.ExecutionContext.Implicits.global
    

    그것을 할 수있는 또 다른 방법은 monix에서 같은 시대를 사용하는 것입니다. 이 방법은 모든 상황에서 작동하지 않습니다, 당신은 여기에 대해 모두 읽을 수 있습니다. 기본적인 아이디어는 때때로 미래가 정말 어떤 시간을 갖지 않고 동기 함수 호출 또는 값의 결과를 반환하므로이 미래가 현재의 thread에 평가 될 수 있다는 것입니다. 이것은 또한 테스트하고 선물을 조롱하는 데 유용합니다. 또한이 예상되는 타임 아웃을 지정할 필요가 없습니다,하지만 여전히 좋은 그것에 대해 걱정할 필요가 없습니다 수 있습니다.

    당신은 당신이 무엇을 얻을보고 기다릴로 다음 손가락을 교차 태스크로 미래를 변환하여 시작하고 같은 시대에 그 작업을 마무리. 이것은 어떻게 작동하는지 보여주기 위해 아주 간단한 예입니다 :

    당신은 그것을 사용할 수 있도록 암시 스케줄러가 필요합니다 :

    import monix.execution.Scheduler.Implicits.global
    

    Coeval(Task.fromFuture(Future (42)).runSyncStep).value() match {
       case Right(v) => println(v)
       case Left(task) => println("Task did not finish")
    }
    

    상기 완료하고 콘솔 지문 42.

    Coeval(Task.fromFuture(Future {
       scala.concurrent.blocking {
          42
       }
    }).runSyncStep).value() match {
       case Right(v) => println(v)
       case Left(task) => println("Task did not finish")
    }
    

    이 예제 인쇄 작업이 완료되지 않았다

  13. ==============================

    13.이 버전은 외부 타이머를 사용하지 않고 작동 (단지 Await.result)

    이 버전은 외부 타이머를 사용하지 않고 작동 (단지 Await.result)

    import scala.concurrent._
    import scala.concurrent.duration.FiniteDuration
    
    object TimeoutFuture {
        def apply[A](
            timeout: FiniteDuration
        )(block: => A)(implicit executor: ExecutionContext): Future[A] =
            try {
                Future { Await.result(Future { block }, timeout) }
            } catch {
                case _: TimeoutException => Future.failed(new TimeoutException(s"Timed out after ${timeout.toString}"))
            }
    }
    
  14. from https://stackoverflow.com/questions/16304471/scala-futures-built-in-timeout by cc-by-sa and MIT license