2015-03-15 2 views
0

Этот сниппетаОчистить OnComplete список функций в Promise

val some = Promise[Int]() 
some.success(20) 
val someFuture = some.future 
someFuture.onSuccess {case i => println(i)} 
someFuture.onComplete {case iTry => List(println(iTry.get*2), println(iTry.get*3))} 

создает обещание со списком 3 обратных вызовов (List[CallbackRunnable]) по полной. Есть ли способ очистить этот список или переписать его?

+0

Не думайте так. Если, возможно, обратный вызов находится в другом «ExecutionContext», который вы можете убить отдельно. –

+1

Не совсем, - вы всегда можете сделать будущее изменчивым и повторно назначить на него. –

+0

@BenjaminGruenbaum Я не думаю, что переназначение будет работать. –

ответ

1

Это технически возможно. Но определенно не так, как вы хотите. Если мы выполним Future (или Promise) в одном ExecutionContext, а обратный вызов в другом случае, мы можем убить обратный вызов ExecutionContext, чтобы он не смог завершить. Это работает в РЕПЛЕ (бросает исключение где-то), но это ужасная идея на самом деле попробовать в реальном коде:

import scala.concurrent._ 
import java.util.concurrent.Executors  

val ex1 = Executors.newFixedThreadPool(1) 
val ex2 = Executors.newFixedThreadPool(1) 
val ec1 = ExecutionContext.fromExecutorService(ex1) 
val ec2 = ExecutionContext.fromExecutorService(ex2) 

val f = Future { Thread.sleep(30000); println("done") }(ec1) // start in one ExecutionContext 

f.onComplete { case t => println("onComplete done") }(ec2) // start callback in another ExecutionContext 

ec2.shutdownNow 

f.onComplete { case t => println("onComplete change") }(ec1) // start another callback in the original ExecutionContext 

Первый onComplete не будет работать (исключение создается в фоновом режиме, что может или не может вызывают ужасные вещи в другом месте), но второй делает. Но это действительно страшно, так что не делайте этого.

Даже если бы существовала конструкция для очистки обратных вызовов, было бы неплохо использовать ее.

someFuture.onComplete { case result => // do something important } 

someFuture.clearCallbacks() // imaginary method to clear the callbacks 

someFuture.onComplete { case result =>> // do something else } 

Выполнение этого гипотетического кода является недетерминированным. someFuture может завершиться до того, как будет вызываться clearCallbacks, что означает как обратные вызовы, а не только второй. Но если он еще не запущен, тогда будет срабатывать только один обратный вызов. Не было бы хорошего способа определить это, что приведет к некоторым действительно ужасным ошибкам.

Смежные вопросы