0

Here is my code :

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();

Here my beloved dwarf :

    public void run() {
        JdbcTemplate localJdbcTemplate = new JdbcTemplate(this.dataSource);
        //dwarf dig in database to find some diamonds
    }

My issue is when I run, arrayis empty. I guess my code is bad-formatted but I'm not comfortable enought with multi threading to find my error. I suppose the array.add() instruction is executed before my thread finishes his work, so value is empty.

What I'm looking for : each thread get his own worker, when worker has result it add the result to my array. For me finally would be executed AFTER my thread retrieve info from db.

I looked at submit method here Returning value from Thread but i'm not sure about how retrieve "future" value. Because if my run method isn't void I get an error.

Azrael_404
  • 426
  • 1
  • 6
  • 17

1 Answers1

3

The ExecutorService in java does not work this way. I guess that you LittleDwarfWorker implmenets Runnable and that the getResult() is your creation. To make is the java way you your worker needs to implements Callable<Object> which allows you to directly get the result after the task has finished. You also need a CompletionService. So you first submit all tasks and afterwards collected their result. The .take() returns a Future<V> which hold you result, so it will block until it is ready.

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();
Westranger
  • 1,308
  • 19
  • 29
  • @Westanger thanks for you explication, at least I understead why my approach was bad. Thanks to you my execution time passed from 2h30 to 8min ! – Azrael_404 Apr 09 '19 at 14:41