4

我有以下代码片段,我想知道Runnable在线程池上运行任务时,在循环中提交实例是否是一种好习惯。

我需要访问循环外的列表,这是我的推理。这是伪代码,所以我的真实代码使用 ConcurrentHashMap 的,消除了线程问题。如果这是不好的做法,有没有人有更好的建议?我尝试将其拆分为另一个课程,但遇到了我的外部列表问题。

我不知道何时从内存中清除列表,我无法知道线程何时全部完成。

public void startJob() {
    int threads = Runtime.getRuntime().availableProcessors();
    ExecutorService exec = Executors.newFixedThreadPool(threads);

    final List<ImportTask> importTasks = session.createCriteria(ImportTask.class).list();
    final List<Object> objs = new ArrayList<>();

    int count = 0;

    for (ImportTask importTask : importTasks) {
        exec.submit(new Runnable() {
            @Override
            public void run() {
                count++;

                if(objs.contains(importTask) {
                    obj = objs.get(importTask.indexOf(importTask));
                } else {
                    Object obj = new Object();
                    objs.add(obj);
                    session.save(obj);
                }


                if(count % 50 = 1000) {
                    session.flush();
                    session.commit();
                }
            }
        }
    }
}
4

2 回答 2

4

将实例提交Runnable到线程池是实现任务并发执行的一种完全有效的方式。

要知道每个任务何时完成,请保留FutureExecutionService.submit().

Future<?> future = exec.submit(new Runnable() {
...
futures.add(future);

最后使用阻塞获得每个未来的结果Future.get()

正如另一个答案所建议的,您也可以使用ExecutorService.invokeAll(). 不同的是,该方法只接受Callable而不是Runnable,必须一次性提交所有任务,并且该方法一直等到最后一个任务终止。

使您的代码更整洁的进一步步骤是使您的任务 ( )ImportTask实现接口Callable(和call方法)并返回它的计算。如果您需要将值传递给任务,例如您的objs列表,您可以通过ImportTask.

于 2013-11-04T11:20:27.097 回答
1

要知道所有线程何时完成,您可以使用“ExecutorService.invokeAll”而不是“submit”。

于 2013-11-04T11:01:15.203 回答