我正在使用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]
}
Run Code Online (Sandbox Code Playgroud)
可能会使用这样的东西:
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]) = …Run Code Online (Sandbox Code Playgroud) 我遇到了Playframework应用程序不时没有响应的问题,我想在运行时检测到这一点,并记录当前在耗尽的执行上下文中运行的内容的日志信息.
实现这一目标的最佳策略是什么?我想过将小的runnables发布到执行上下文中,如果它们没有及时执行,我会记录一个警告.这个最大等待时间当然应该是可配置的.例如,主Web执行上下文永远不应被阻止超过1秒,但后台db执行上下文可能允许30秒阻塞.
有人必须先做过这件事吗?
相关信息:http: //www.playframework.com/documentation/2.2.x/ThreadPools
为JavaScript中的每个函数创建一个新的执行上下文.
运行以下代码时,内存中存在多少个执行上下文?请注意,Bar不会调用该函数.
function Foo () {
function Bar() {}
}
Foo();
Run Code Online (Sandbox Code Playgroud)
此外,何时创建执行上下文?在评估时或运行时?
出于某种原因,我无法解决这个问题.我有一个运行Play的应用程序调用Elastic Search.作为我的设计的一部分,我的服务使用包含scala future的Java API,如本博文中所示.我已经更新了该帖子中的代码以提示ExecutionContext,它将执行一些阻塞I/O,如下所示:
import scala.concurent.{blocking, Future, Promise}
import org.elasticsearch.action.{ActionRequestBuilder, ActionListener, ActionResponse }
def execute[RB <: ActionRequestBuilder[_, T, _, _]](request: RB): Future[T] = {
blocking {
request.execute(this)
promise.future
}
}
Run Code Online (Sandbox Code Playgroud)
我构建查询以发送给ES的实际服务将executionContext作为构造函数参数,然后用于调用弹性搜索.我这样做是为了让播放使用的全局执行上下文不会让它的线程被ES的阻塞调用所束缚.这个SO评论提到只有全局上下文才能阻塞,所以这让我不得不创建自己的.在同一个帖子/答案中有很多关于使用ForkJoin池的信息,但是我不确定如何使用这些文档中的内容并将其与阻塞文档中的提示相结合来创建响应阻塞的执行上下文提示.
我认为我遇到的一个问题是,我不确定如何首先如何回应阻止上下文?我正在阅读最佳实践,它使用的示例是一个无限的线程缓存:
请注意,在这里我更喜欢使用无限制的"缓存线程池",因此它没有限制.在阻塞I/O时,我们必须拥有足够的线程来阻止I/O. 但是如果无界限太多,取决于用例,你可以稍后对其进行微调,这个样本的想法是你得到了滚动.
那么这是否意味着我的ForkJoin支持的线程池,我应该尝试在处理非阻塞I/O时使用缓存线程并创建一个新线程来阻止IO?或者是其他东西?几乎我在网上找到的关于使用单独线程池的每个资源都倾向于执行新手指南所做的事情,也就是说:
如何调整各种线程池在很大程度上取决于您的个人应用程序,超出了本文的范围.
我知道这取决于你的应用程序,但在这种情况下,如果我只想创建某种类型的阻塞感知ExecutionContext并理解管理线程的合适策略.如果Context专门用于应用程序的单个部分,那么我应该只是制作一个固定的线程池大小而不是首先使用/忽略该blocking关键字吗?
我倾向于絮絮叨叨,所以我会试着在答案中分解我正在寻找的东西:
blocking那里的关键部分.对不起,这里有一个很长的问题,我只是想让你了解我正在看的东西,并且我一直试图绕过这一天超过一天需要一些外界的帮助.
编辑:为了清楚起见,ElasticSearch Service的构造函数签名是:
//Note that these are not implicit parameters!
class …Run Code Online (Sandbox Code Playgroud) 当鼠标触发单击事件时,它的行为符合预期:
首先,侦听器 1 被推入堆栈,并在微任务队列(或作业队列)中对 Promise 1 进行排队。当侦听器 1 弹出时,堆栈变空。Promise 1 回调在侦听器 2 之前执行(侦听器 2 在任务队列(或回调队列)中等待)。在 Promise 1 回调弹出后,侦听器 2 被压入堆栈。因此输出为:
侦听器 1 微任务 1 侦听器 2 微任务 2
但是,当通过 JavaScript 代码触发点击时,其行为会有所不同:
即使在 click() 函数完成之前,回调也会被推入堆栈(即调用堆栈不为空)。这里的输出是:
监听器 1 监听器 2 微任务 1 微任务 2
这是代码:
window.onload = function(){
document.getElementById("myBtn").addEventListener('click', () => {
Promise.resolve().then(() => console.log('Microtask 1'));
console.log('Listener 1');
} );
document.getElementById("myBtn").addEventListener('click', () => {
Promise.resolve().then(() => console.log('Microtask 2'));
console.log('Listener 2');
} );
}
function clickB(){
document.getElementById("myBtn").click();
}Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>
<button id="myBtn">Manual …Run Code Online (Sandbox Code Playgroud)我想了解JavaScript范围规则.我在教科书和文档中看到的内容令人困惑.
在我看来,JavaScript是一种静态(或词汇)范围的语言 - 当尝试将变量名称绑定到变量(定义)时,使用代码的词法结构.
执行上下文似乎类似于调用堆栈上的堆栈帧.每个执行上下文都有一个变量对象,在该变量对象上定义了(相关函数的)所有局部变量.这些变量对象链接在一起,以提供从堆栈顶部的变量对象到堆栈底部的变量对象(窗口对象)的"范围链".在将变量名称绑定到变量时,从上到下搜索此作用域链.这与静态范围的语言(如C/C++/Java)非常相似.
对于C/C++/Java,似乎有一个重要的区别 - 可以访问函数中定义的变量,该函数的堆栈帧不再位于调用堆栈上,如下例所示:
var color = "red";
var printColor;
function changeColor() {
var color = "green";
printColor = function(msg) {
alert(msg + color);
}
printColor("in changeColor context, color = "); // "green"
}
changeColor();
// stack frame for "changeColor" no longer on stack
// but we can access the value of the variable color defined in that function
printColor("in global context, color = "); // "green"
Run Code Online (Sandbox Code Playgroud)
我做对了吗?我还应该注意其他问题吗?
提前致谢
我的Scala代码中有一些同步调用。我将它们包装在blocking()上下文中,然后在Future中:Future(blocking(syncCall())),但是我不知道要使用哪种类型的ExecutionContext。
我知道可能存在很多可能性,并且没有ExecutionContext是“最佳”的。我只需要一些信息,以免选择最差的一种,因为那里有很多信息,而且我头上一团糟。
function foo(a,b){
return a + b;
}
foo(1,2);Run Code Online (Sandbox Code Playgroud)
函数参数是否提升?
函数执行上下文创建阶段的变量环境是否看起来像这样:
VE = {
{ 0 : undefined , 1: undefined, length: 2 },
{a : undefined, b: undefined},
outer: refToGlobalLE
}
Run Code Online (Sandbox Code Playgroud) 假设我有一个 HTTP 客户端来调用具有请求速率限制的服务器,例如 1000 个请求/秒。我像这样实现了速率限制器ExecutionContext:
使用Guava的RateLimiter创建了一个有界阻塞队列
class MyBlockingQueue[A](capacity: Int, permitsPerSecond: Int)
extends ArrayBlockingQueue[A](capacity) {
private val rateLimiter = RateLimiter.create(permitsPerSecond.toDouble)
override def take(): A = {
rateLimiter.acquire()
super.take()
}
override def poll(timeout: Long, unit: TimeUnit): A = {
rateLimiter.tryAcquire(timeout, unit) // todo: fix it
super.poll(timeout, unit)
}
}
Run Code Online (Sandbox Code Playgroud)
ExecutionContext使用此队列创建了一个ThreadPoolExecutor。
def createRateLimitingExecutionContext(numThreads: Int,
capacity: Int,
permitsPerSecond: Int): ExecutionContext = {
val queue = new MyBlockingQueue[Runnable](capacity, permitsPerSecond)
val executor = new ThreadPoolExecutor(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, queue) …Run Code Online (Sandbox Code Playgroud) 我以为我掌握了提升的概念,但下面的代码让我感到困惑。怎么返回1呢?第二个 example() 函数会被提升到第一个函数之上吗?
function example() {
return 9;
}
console.log(example());
function example() {
return 1;
}Run Code Online (Sandbox Code Playgroud)
如果在编译阶段提升函数声明并在执行阶段执行函数表达式。下面的代码为什么返回7?这仅仅是因为首先声明了示例表达式吗?
var example = function() {
return 7;
}
console.log(example());
function example() {
return 0;
}Run Code Online (Sandbox Code Playgroud)
先感谢您!
executioncontext ×10
javascript ×5
scala ×5
concurrency ×2
hoisting ×2
akka ×1
blocking ×1
callstack ×1
dom-events ×1
event-loop ×1
io ×1
java ×1
scala-2.10 ×1
scope ×1
threadpool ×1