用线程处理列表的智能方法

时间:2011-03-21 22:19:15

标签: java multithreading

我有一个只读数据列表,这些数据是互联网上我要处理的一堆终点。我想知道是否有任何类型的内置类或模式我应该遵循处理这个?

现在我只是将初始列表放入 N 块并创建 N 线程来处理每个请求。

6 个答案:

答案 0 :(得分:4)

使用ExecutorService来处理并发处理。

public void processAll(List<Endpoint> endpoints, int numThreads) {
    ExecutorService executor = Executors.newFixedThreadPool(numThreads);

    for(final Endpoint endpoint : endpoints) {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                doProcessing(endpoint);
            }
        });
    }
    // instead of a loop, you could also use ExecutorService#invokeAll()
    // with the passed-in list if Endpoint implements
    // java.util.concurrent.Callable

    executor.shutdown();
}

private void doProcessing(Endpoint endpoint) {
    // do whatever you do with each one
}

这只是一个简单的例子。有关如何使用更具体类型的ExecutorService,处理Futures以及执行各种漂亮工作的示例,请查看API。

答案 1 :(得分:3)

答案 2 :(得分:2)

听起来像Queue(使用java.util.concurrent中的一个实现)就是您所需要的。这样每个线程都可以在准备就绪时获取链接,这比预先分区更有意义。

答案 3 :(得分:1)

你需要三个想法:

  • 两个阻止列表 - 首先是数据到porcess,第二个是结果
  • 执行人服务
  • 某种闩锁

我的示例应用程序:

public class App {

    private static final int NUMBER_OF_THREADS = 3;

    public static void main(String[] args) throws InterruptedException {

        BlockingQueue<String> data = prepareData();

        BlockingQueue<String> results = new LinkedBlockingQueue<String>();

        ExecutorService executor = Executors.newFixedThreadPool(3);
        CountDownLatch countDownLatch = new CountDownLatch(3);

        for (int i = 0; i < NUMBER_OF_THREADS; i++)
            executor.execute(new Processor<String>(data, results,
                    countDownLatch, i + ""));

        countDownLatch.await();
    }

    private static BlockingQueue<String> prepareData() {
        BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
        for (int i = 0; i < 1000; i++) {
            queue.add(i + "");
        }
        return queue;
    }

}

class Processor<T> implements Runnable {

    private BlockingQueue<T> dataSource;

    private CountDownLatch latch;

    private String name;

    private BlockingQueue<String> results;

    public Processor(BlockingQueue<T> dataSource,
            BlockingQueue<String> results, CountDownLatch countDownLatch,
            String processName) {
        this.dataSource = dataSource;
        this.results = results;
        this.latch = countDownLatch;
        this.name = processName;
    }

    @Override
    public void run() {
        T t = null;
        while ((t = dataSource.poll()) != null) {
            try {
                String result = "Process " + name + " processing: "
                        + t.toString();
                System.out.println(result);
                results.put(result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        latch.countDown();
    }
}

准备数据后,创建一些处理器来处理数据。每个处理器都引用了线程保存数据源。获取对象,处理它们,最后将结果放到另一个包含结果的线程保存集合中。

当数据源变空时,请调用 latch.countDown(),向等待结果的主线程或线程说“完成所有操作”。

答案 4 :(得分:0)

查看java.util.concurrent包和ExecutorService。

Brian Goetz的书“实践中的Java并发”是理解这些内容的必要条件。

答案 5 :(得分:0)

阻止队列可能是最适合您的方式。谷歌它,你会发现很多信息,这是一个很好的教程:http://www.developer.com/java/ent/article.php/3645111/Java-5s-BlockingQueue.htm