scala – 将隐式ExecutionContext传递给包含的对象/被调用的方法
发布时间:2020-12-16 09:27:17 所属栏目:安全 来源:网络整理
导读:我正在使用Scala 2.10期货创建一个异步库.库的构造函数采用一系列实现特定特征的用户定义对象,然后库类上的方法将一些数据逐个发送到用户定义的对象中.我希望用户在设置主实例时为异步操作提供ExecutionContext,然后根据需要将该上下文传递给用户定义的对象.
我正在使用Scala 2.10期货创建一个异步库.库的构造函数采用一系列实现特定特征的用户定义对象,然后库类上的方法将一些数据逐个发送到用户定义的对象中.我希望用户在设置主实例时为异步操作提供ExecutionContext,然后根据需要将该上下文传递给用户定义的对象.简化(伪?)代码:
case class Response(thing: String) class LibraryObject(stack: Seq[Processor])(implicit context: ExecutionContext) { def entryPoint(data: String): Future[Response] = { val response = Future(Response("")) stack.foldLeft(response) { (resp,proc) => proc.process(data,resp) } } } trait Processor { def process(data: String,resp: Future[Response]): Future[Response] } 可能会使用这样的东西: class ThingProcessor extends Processor { override def process(data: String,response: Future[Response]) = { response map { _.copy(thing = "THE THING") } } } class PassThroughProcessor extends Processor { override def process(request: Request,response: Future[Response]) = { response } } object TheApp extends App { import ExecutionContext.Implicits.global val stack = List( new ThingProcessor,new PassThroughProcessor ) val libObj = new LibraryObject(stack) val futureResponse = libObj.entryPoint("http://some/url") // ... } 我收到ThingProcessor的编译错误:
我的问题是,我如何隐式地将LibraryObject所具有的ExecutionContext提供给用户定义的对象(ThingProcessor和PassThroughProcessor)或他们的方法而不让用户(谁将编写类)担心它 – 也就是说,我希望用户不必键入: class MyFirstProcessor(implicit context: ExecutionContext) 要么 override def process(...)(implicit context: ExecutionContext) = { ... } 解决方法
隐式作用域包括伴随对象和基类的类型参数.
或者,library.submit(new library.Processor {def process()…}). 这是有效的,但不是我的第一个想法,这是更聪明的: import concurrent._ import concurrent.duration._ class Library(implicit xc: ExecutionContext = ExecutionContext.global) { trait Processor { implicit val myxc: ExecutionContext = xc def process(i: Future[Int]): Future[Int] } def submit(p: Processor) = p process future(7) } object Test extends App { val library = new Library val p = new library.Processor { def process(i: Future[Int]) = for (x <- i) yield 2 * x } val res = library submit p val z = Await result (res,10.seconds) Console println z } 更新: import concurrent._ import concurrent.duration._ import java.util.concurrent.Executors class Library()(implicit xc: ExecutionContext = ExecutionContext.global) { trait Processor { implicit val myxc: ExecutionContext = xc def process(i: Future[Int]): Future[Int] } def submit(p: Processor) = p process future(7) } object ctx { val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor } object library1 extends Library object library2 extends Library()(ctx.xc) object p extends library1.Processor { def process(i: Future[Int]) = for (x <- i) yield 2 * x } object q extends library2.Processor { def process(i: Future[Int]) = for (x <- i) yield 3 * x } object Test extends App { val res = library1 submit p //val oops = library2 submit p //val oops = library1 submit q val z = Await result (res,10.seconds) Console println z Console println (Await result (library2 submit q,10.seconds)) ctx.xc.shutdownNow() } 它不是一件容易的事: class Library(implicit xc: ExecutionContext = ExecutionContext.global) { def submit(p: Processor): Future[Int] = p dueProcess future(7) } trait Processor { implicit var myxc: ExecutionContext = _ def dueProcess(i: Future[Int])(implicit xc: ExecutionContext) = { myxc = xc process(i) } protected def process(i: Future[Int]): Future[Int] } object ctx { val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor } object Test extends App { def db() = Console println (new Throwable().getStackTrace mkString ("TRACE [n ","n ","n]")) val library = new Library()(ctx.xc) val p = new Processor { protected def process(i: Future[Int]) = for (x <- i) yield { db(); 2 * x } } val res = library submit p val z = Await result (res,10.seconds) Console println z ctx.xc.shutdownNow() } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |