1

我有一个Response对象用于表示对 Web 服务的发布响应。鉴于此代码:

Response resp1= Server.request(a);
Response resp2= Server.request(b);
Response resp3= Server.request(c);
if (resp1.isOk() && resp2.isOk() && resp3.isOk()){
    // Do stuff
}

由于服务器有点慢,我想在 3 个线程中并行化请求。但我不知道如何让主线程等待结果并检索 3 个响应。

4

3 回答 3

1

您有一些基于线程的方法。

  • 第一个是公开一个阻塞调用,例如,

    resp1.waitFoCompletion();

  • 二是提供轮询机制(不是很好)

    while(resp1.isCompleted())

  • 第三是提供一个回调,例如,您的主类可以实现

    interface Callback() { void onCompletion(Result result); }

但是一个重要的问题是,当您可以使用例如 时,为什么要自己这样做Executors

于 2012-08-30T15:38:03.413 回答
1

你不能。您将不得不分拆三个单独的线程,然后让主线程轮询三个线程并等待一段时间(如果它们没有完成)。如果您知道您的哪些服务很慢,您可以在为其他服务启动单独的线程后让主线程调用该服务,但您仍然必须处理其他一个在异常情况下需要更长时间的情况。

不过,有几条评论:如果这确实是一个加载问题,那么关闭额外的线程可能无济于事,而且实际上可能会受到伤害。这种方法只有在多个服务确实很慢时才会有所帮助,因为它们需要为这个调用做很多事情(而不是因为它们处于负载之下)。另外,它们必须在单独的硬件上;如果这些真的是共享硬件,那么你只会得到并行运行的错觉,因为每个都减慢了其他的速度,无论如何,只是以多线程的方式。

最后,您不应该无所适从地推出新线程。它们是一种相对昂贵的消耗性资源。你应该有一个线程池,这样它们的数量永远不会超过 N,而且你必须非常小心,它们永远不会落入黑洞。所以所有线程都需要超时,并且进程必须在所有可能的错误情况下始终清理并将线程返回到池中。

编辑:上一张海报建议使用 Executors,他还提到了回调。如果您按照他的链接,您会看到 Executor 的默认实现不会分离单独的线程,它只是等待完成,因此不会让您获得并行性。然而,executor-with-a-callback 模式是一个很好的实现线程池和集成我上面提到的轮询和等待机制的模式。您的执行程序处理线程池并启动任务,然后调用回调。您的主线程使用任务创建执行程序,而回调只是在主线程的对象中设置标志的东西。现在您的主线程只需要一个循环来查找所有设置的标志并等待。

于 2012-08-30T15:42:15.957 回答
1

我想你可以做这样的事情来启动 3 个线程中的调用并等待它们的终止:

private Response resp1, resp2, resp3;

protected void doRequests() {
    Thread thread1 = new Thread() {
        public void run() {
            resp1= Server.request(a);           
        }
    };
    Thread thread2 = new Thread() {
        public void run() {
            resp1= Server.request(a);           
        }
    };
    Thread thread3 = new Thread() {
        public void run() {
            resp1= Server.request(a);           
        }
    };

    thread1.start();
    thread2.start();
    thread3.start();

    try { thread1.join(); } catch(InterruptedException e) { }
    try { thread2.join(); } catch(InterruptedException e) { }
    try { thread3.join(); } catch(InterruptedException e) { }
}
于 2012-08-30T15:45:48.610 回答