从 Java 线程返回值

2022-09-02 05:05:13

我有一个像这样的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 次数据库。

任何想法,我怎么能做到这一点?


答案 1

规范方法是使用 a 和 .将 a 转换为 a 将返回一个(类型安全),您可以从中得出结果。CallableExecutorServicesubmitCallableExecutorServiceFutureget

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

在您的例子中,您可能希望使用 哪个返回 a of ,或者在向执行器添加任务时自己创建该列表。要收集结果,只需调用每个结果即可。invokeAllListFuturesget


答案 2

如果要在执行数据库更新之前收集所有结果,可以使用 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. */
...

推荐