2012-03-09 100 views
1

我有一个Java客户端需要递归调用服务器来检索大型数据图 - 需要大约一千个调用。我无法控制服务器,这对于时间紧急的故障恢复场景是必需的。递归作用/ ForkJoinPool阻塞I/O

我的问题是,我需要我的原始线程阻塞,直到所有通话都完成。

java.util.concurrent的RecursiveAction和ForkJoinPool抽象正是我所需要的,除了它们是为CPU并行性设计的并且禁止使用阻塞I/O。

那么,实现递归网络调用的最佳方式是什么?在启动线程阻塞之前,所有调用都已完成?

其他方面信息:

  • 我不能修改服务器。
  • 服务器允许并支持这种重查询。
  • 我将限制并发网络调用的数量为10-30。
  • 在磁盘上缓存数据不可行。

其他想法:单相Phaser是否适合与ThreadPoolExecutor一起使用?调用任务将调用Phaser.register(),进行调用,提交子任务,然后调用Phaser.arrive()。启动线程将调用Phaser.awaitAdvance(1)。这是最合适的方法吗?

回答

3

使用JDK1.7 Phasers可以很好地工作。我使用的模式是这样的:

private void loadGraphFromServer() { 
    final Phaser phaser = new Phaser(1); // "1" registers the calling thread 
    for (final Item item : getDataListFromServer()) { 
     phaser.register(); 
     executorService.submit(new Runnable() { 
      public void run() { 
       try { 
        getMoreDataFromServer(item.getSomeId()); 
        // more nested loops/tasks/calls here... 
       } 
       finally { 
        phaser.arrive(); 
       } 
      } 
     }); 
    } 
    phaser.arriveAndAwaitAdvance(); // blocks until all tasks are complete 
} 
0

我会尝试使用固定大小的执行程序池。您可以将最大大小设置为10到30个线程,并将其分配给所有1000个请求,也可以添加1个请求来创建另外两个,还有另外两个等等。您可以等待所有这些请求使用shutdown()和awaitTermination ()

+0

谢谢,但我不能使用shutdown/awaitTermination,因为启动线程不知道何时提交最后一个任务。 – Paul 2012-03-09 09:42:11

+0

每个任务都可以等待它创建的任务。它可以做尾部优化,即如果它最后要做的事情不要创建另一个任务。 – 2012-03-09 10:41:00

+2

但后来我用尽了线程......除非我失去了一些东西。 – Paul 2012-03-09 10:57:36