基本问题: 如果我对一个执行长计算(60秒或更长时间)的控制器方法进行AJAX调用,我会得到一个复制的线程进入并遵循相同的执行路径(尽管我可以从堆栈跟踪转储中得知 - 并且只有一个,这不会继续发生在第二个线程中)。这似乎只有在通过AJAX调用控制器操作时才会发生。这可以通过创建一个虚拟控制器方法来轻松复制,该方法在完成时返回的Thread.sleep()调用中没有任何内容。
我已经在一个没有AJAX调用的情况下加载的方法中对此进行了测试,并且它不会产生流氓线程。我尝试了各种形式的AJAX调用(几种形式的jQuery方法和基本JavaScript)并且每种方法得到了相同的结果。我最初认为它可能是一个线程问题所以我使用Promise(s)(http://www.playframework.com/documentation/2.1.x/JavaAsync和http://www.playframework.com/documentation/2.1.x/JavaAkka)和AsyncResult实现了虚拟方法,但它没有效果。
我知道这两个线程正在使用相同的执行上下文。这是导致问题吗?将长计算移动到另一个上下文是否可以避免?关于第二个重复线程来自何处的任何想法?
控制器方法(长计算):
public static Result test()
{
Logger.debug("*** TEST Controller entry: threadId=" + Thread.currentThread().getId());
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
for(StackTraceElement e : stack)
{
Logger.debug("***" + e.toString());
}
Promise<Void> promiseString = Akka.future(
new Callable<Void>() {
public Void call() {
try
{
Logger.debug("*** going to sleep: threadId=" + Thread.currentThread().getId());
Thread.sleep(90000);
}
catch(InterruptedException e)
{
//swallow it whole and move on
}
return null;
}
}
);
Promise<Result> promiseResult = promiseString.map(
new Function<Void, Result>() {
public Result apply(Void voidParam) {
return ok("done");
}
}
);
return async(promiseResult);
}