具有阻塞I / O的RecursiveAction / ForkJoinPool

时间:2012-03-09 07:32:38

标签: java concurrency

我有一个Java客户端需要递归调用服务器来检索大型数据图 - 需要大约一千个调用。我无法控制服务器,这对于时间要求严格的崩溃恢复方案是必需的。

我的问题是我需要阻止原始线程直到所有呼叫都完成。

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

那么,实施递归网络调用的最佳方法是什么,启动线程阻塞直到所有调用都完成?

其他背景信息:

  • 我无法修改服务器。
  • 服务器允许并支持这种大量查询。
  • 我会将并发网络呼叫的数量限制为10-30。
  • 在磁盘上缓存数据是不可行的。

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

2 个答案:

答案 0 :(得分:4)

使用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
}

答案 1 :(得分:0)

我会尝试使用固定大小的执行程序池。您可以将最大大小设置为10到30个线程并将其与所有1000个请求进行批量处理,或者添加1个请求以创建另外两个,以及另外两个等等。您可以等待所有这些请求完成,使用shutdown()和awaitTermination ()