我有一个只读数据列表,这些数据是互联网上我要处理的一堆终点。我想知道是否有任何类型的内置类或模式我应该遵循处理这个?
现在我只是将初始列表放入 N 块并创建 N 线程来处理每个请求。
答案 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)
您无法使用适当的并发容器的任何原因? http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html
答案 2 :(得分:2)
听起来像Queue
(使用java.util.concurrent
中的一个实现)就是您所需要的。这样每个线程都可以在准备就绪时获取链接,这比预先分区更有意义。
答案 3 :(得分:1)
你需要三个想法:
我的示例应用程序:
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