玩框架,承诺,非阻塞线程编程

时间:2015-03-03 12:39:27

标签: java playframework promise nonblocking

function1()对function2()有什么好处(除了执行两个GET查询时的小并行性)?在我看来,控制器线程在两种情况下都是非阻塞的,但在等待结果时必须阻止其中一个后台线程。有关更好的示例,当我们查看function3()时,我们看到databaseDao线程被阻塞,直到操作完成(使用dao JPA内部)。

public static F.Promise<Result> function1() {
    final F.Promise<WSResponse> twitterPromise = WS.url("http://www.twitter.com").get();
    final F.Promise<WSResponse> typesafePromise = WS.url("http://www.typesafe.com").get();

    return twitterPromise.flatMap((twitter) -> typesafePromise.map((typesafe) -> ok(twitter.getBody() + typesafe.getBody())));
}

public static F.Promise<Result> function2() {
    F.Promise<String> promise = F.Promise.promise(() -> {
        HttpClient client = HttpClientBuilder.create().build();
        HttpGet request1 = new HttpGet("http://www.twitter.com");
        HttpGet request2 = new HttpGet("http://www.typesafe.com");

        HttpResponse response = client.execute(request1);
        HttpResponse response2 = client.execute(request2);

        // result is not important
        return response.toString() + response2.toString();
    });

    return promise.map(Results::ok);
}

public static F.Promise<Result> function3() {
    F.Promise<String> promise = F.Promise.promise(() -> databaseDao.longRunningOperation());

    return promise.map(Results::ok);
}

如果函数阻塞,我们的后台线程池就会快速消失。那么非盈利游戏框架和承诺超过Spring框架和tomcat?

编辑:

public static F.Promise<Result> function4() {
    F.Promise<String> promise = F.Promise.promise(() -> {
        HttpClient client = HttpClientBuilder.create().build();
        HttpGet request1 = new HttpGet("http://www.twitter.com");
        HttpResponse response = client.execute(request1);

        return response.toString();
    });

    F.Promise<String> promise2 = F.Promise.promise(() -> {
        HttpClient client = HttpClientBuilder.create().build();
        HttpGet request2 = new HttpGet("http://www.typesafe.com");
        HttpResponse response2 = client.execute(request2);
        return response2.toString();
    });

    return promise.flatMap(p1 -> promise2.map(p2 -> ok(p1 + p2)));
}

上面的函数阻塞了两个线程,所以它比function1更糟糕?但执行时间可以比较。例如,如果promise1需要5秒,而promise2需要4秒,结果将在5秒内完成?

1 个答案:

答案 0 :(得分:2)

  

function1()对function2()有什么好处(除了执行两个GET查询时的小并行性)?

它不仅仅是并行性。 Play WS构建于AsyncHttpClient之上,AsyncHttpClient是一种非阻塞API。在function2中,您似乎正在使用Apache HttpClient,这是一个阻止API。并行性有所帮助。正如@Salem已经说过,function1只会是最长的请求,而function2每次都会占用两个请求。

  

在我看来,控制器线程在两种情况下都没有被阻止,......

是的,只要Promise被移到另一个ExecutionContext,我们就不会阻止Play内幕。

  

...但在等待结果时必须阻止其中一个后台线程。

不正确。由于function1仅调用WS API(异步),因此不会阻止等待响应的任何线程。 function2可能不会阻止负责控制器功能的线程,但它必须阻塞某个地方。这并不是说将它包装在Promise中是一个坏主意 - 如果它必须阻止,它也可以在其他地方进行。

  

...看看function3()我们看到databaseDao线程被阻塞,直到操作完成(使用dao JPA内部)。

事实上,大多数数据库驱动程序都会阻塞,除了尝试不太流行的异步驱动程序之外,除了尝试不那么流行的异步驱function2function3的行为与function1function2的行为更相似。 function真的属于它自己的一类。

  

如果函数阻塞,我们的后台线程池就会快速消失。

是的,但是大多数时候我们必须阻止某个地方,如果您可以选择使用异步API,那么很棒。例如,出于上述原因,我总是使用function1而不是function2。但是对于数据库调用,我使用了阻塞API,因为在数据库中读取数据的应用程序中,如果我的数据库已经超载了查询,保存一些应用程序线程将无法帮助我。 / p>

  

上面的函数[function4]阻塞了两个线程,所以它比function1更糟糕?但执行时间可以比较。例如,如果promise1需要5秒,而promise2需要4秒,结果将在5秒内完成?

function4更糟糕的是,它比function1阻止了更多。这是否会立即影响您的应用程序的性能取决于您是否反对您的线程数。但是我没有理由选择function4而不是function1function4可以在与function1相同的时间内完成,提供它具有必要的线程来执行此操作。如果池中只有一个可用线程,则第二个promise可能必须等待第一个在执行之前完成。在function1中,这不会发生。