我有一个Java线程,如下所示:
public class MyThread extends Thread {
MyService service;
String id;
public MyThread(String id) {
this.id = node;
}
public void run() {
User user = service.getUser(id)
}
}
我有大约300个id,每隔几秒钟-我会启动线程来调用每个id。例如:
for(String id: ids) {
MyThread thread = new MyThread(id);
thread.start();
}
现在,我想收集每个线程的结果,并对数据库执行一次批量插入,而不是每2秒执行300次数据库插入。
你知道我该怎么做吗?
发布于 2010-02-23 06:00:18
如果希望在进行数据库更新之前收集所有结果,可以使用invokeAll
方法。这就像daveb建议的那样,如果你一次提交一个任务,就需要记账。
private static final ExecutorService workers = Executors.newCachedThreadPool();
...
Collection<Callable<User>> tasks = new ArrayList<Callable<User>>();
for (final String id : ids) {
tasks.add(new Callable<User>()
{
public User call()
throws Exception
{
return svc.getUser(id);
}
});
}
/* invokeAll blocks until all service requests complete,
* or a max of 10 seconds. */
List<Future<User>> results = workers.invokeAll(tasks, 10, TimeUnit.SECONDS);
for (Future<User> f : results) {
User user = f.get();
/* Add user to batch update. */
...
}
/* Commit batch. */
...
发布于 2010-02-23 05:39:27
规范的方法是使用Callable
和ExecutorService
。将Callable
设置为ExecutorService
会返回一个(类型安全的) Future
,您可以从中get
结果。
class TaskAsCallable implements Callable<Result> {
@Override
public Result call() {
return a new Result() // this is where the work is done.
}
}
ExecutorService executor = Executors.newFixedThreadPool(300);
Future<Result> task = executor.submit(new TaskAsCallable());
Result result = task.get(); // this blocks until result is ready
在您的示例中,您可能希望使用返回Futures
List
的invokeAll
,或者在向executor添加任务时自己创建该列表。要收集结果,只需对每个结果调用get
。
发布于 2010-02-23 06:07:58
将结果存储在对象中。当它完成时,让它把自己放到一个同步的集合中(想到的是一个同步队列)。
当您希望收集要提交的结果时,从队列中抓取所有内容,并从对象中读取结果。您甚至可以让每个对象知道如何将它自己的结果"post“到数据库中,这样就可以提交不同的类,并使用完全相同的小而优雅的循环来处理所有类。
JDK中有很多工具可以帮助你做到这一点,但是一旦你开始把你的线程看作一个真正的对象,而不只是一堆关于"run“方法的废话,事情就变得很简单了。一旦你开始以这种方式思考对象,编程就会变得更加简单和令人满意。
https://stackoverflow.com/questions/2314402
复制相似问题