Вот мой код:
List<Object> array= new ArrayList<Object>();
int i=0;
ExecutorService pool = Executors.newFixedThreadPool(50);
for(String str : strList) {
LittleDwarfWorker littleDwarfWorker = new LittleDwarfWorker(params including a datasource);
try {
pool.execute(littleDwarfWorker);
}catch(Exception e) {
e.printStackTrace();
}
finally{
i++;
array.add(littleDwarfWorker.getResult());
if ((i%100)==0) {
log.info("Progression :"+i+"/"+listeEan.size());
}
}
}
pool.shutdown();
Вот мой любимый гномик:
public void run() {
JdbcTemplate localJdbcTemplate = new JdbcTemplate(this.dataSource);
//dwarf dig in database to find some diamonds
}
Моя проблема в том, что когда я бегу, array
пусто. Я предполагаю, что мой код плохо отформатирован, но мне недостаточно удобно работать с многопоточностью, чтобы найти свою ошибку. Я предполагаю, что инструкция array.add()
выполняется до того, как мой поток закончит свою работу, поэтому значение пусто.
Что я ищу:
каждый поток получает своего собственного рабочего, когда у рабочего есть результат, он добавляет результат в мой массив.
Для меня finally
будет выполняться ПОСЛЕ того, как мой поток получит информацию из БД.
Я посмотрел здесь метод отправки Возвращаемое значение из потока, но я не уверен, как получить «будущее» значение. Потому что, если мой метод запуска не пуст, я получаю сообщение об ошибке.
ExecutorService
в java так не работает. Я предполагаю, что вы LittleDwarfWorker implmenets Runnable
и что getResult() — ваше творение. Чтобы сделать это Java, как вам нужно вашему работнику implements Callable<Object>
, что позволяет вам напрямую получить результат после завершения задачи. Вам также понадобится CompletionService
. Таким образом, вы сначала отправляете все задачи, а затем собираете их результат. .take()
возвращает Future<V>
, который содержит ваш результат, поэтому он будет блокироваться, пока не будет готов.
ExecutorService executor = Executors.newFixedThreadPool(50);
CompletionService<Obejct> completionService = new ExecutorCompletionService<> (executor);
for(String str : strList) {
completionService.submit(new LittleDwarfWorker(...));
}
for ( int i = 0; i < strList.size(); i++ ) {
try {
Object result = completionService.take().get();
// ... do whatever something with the object
} catch ( InterruptedException | ExecutionException e ) {
e.printStackTrace();
}
}
executor.shutdown();
@Westanger спасибо за объяснение, по крайней мере, я понимаю, почему мой подход был плохим. Благодаря вам мое время выполнения сократилось с 2 часов 30 минут до 8 минут!