Using Callable in java runs code sequentially

Asked

Viewed 160 times

4

I am making a server in java wanted to perform certain tasks in parallel. I have a list of a certain type I want 20 threads to deal with elements of the list.

for( Item item : result ) {
    Callable< List< IResult > > callable = new HTMLParser( item ); 
    Future< List< IResult > > future = pool.submit( callable );
    set.add( future );
}

for( Future< List< IResult > >  future : set ) {
    List< IResult > result = future.get( ); // wait for a processor to complete
    if( result != null && !result.isEmpty( ) )
        FResults.addAll( result ); 
    }
}

Only running this hiccup, analyzing the logs seems to me to be running the threads sequentially

2016-12-06 14:17:02.106 DEBUG 18229 --- [pool-1-thread-5] ......
2016-12-06 14:17:02.106 DEBUG 18229 --- [pool-1-thread-5] ....
2016-12-06 14:17:02.106 DEBUG 18229 --- [pool-1-thread-5] .....
2016-12-06 14:17:02.106 DEBUG 18229 --- [pool-1-thread-5] .......
2016-12-06 14:17:02.106  INFO 18229 --- [pool-1-thread-5] .....
2016-12-06 14:17:02.243 DEBUG 18229 --- [ool-1-thread-19] .....
2016-12-06 14:17:02.243  INFO 18229 --- [ool-1-thread-19] ....
2016-12-06 14:17:02.587 DEBUG 18229 --- [ool-1-thread-16] .....
2016-12-06 14:17:02.587 DEBUG 18229 --- [ool-1-thread-16] ....
2016-12-06 14:17:02.587 DEBUG 18229 --- [ool-1-thread-16] .....
2016-12-06 14:17:02.587 DEBUG 18229 --- [ool-1-thread-16] .....
2016-12-06 14:17:02.588 DEBUG 18229 --- [ool-1-thread-16] .....
2016-12-06 14:17:02.588 DEBUG 18229 --- [ool-1-thread-16] ......
2016-12-06 14:17:02.588 DEBUG 18229 --- [ool-1-thread-16] .....
2016-12-06 14:17:02.588 DEBUG 18229 --- [ool-1-thread-16] ....
2016-12-06 14:17:02.588 DEBUG 18229 --- [ool-1-thread-16] ......
2016-12-06 14:17:02.588 DEBUG 18229 --- [ool-1-thread-16] ...

The logs of a thread appears sequentially all in a row, it doesn’t make sense to me. Any idea ?

  • What is the configuration of pool? Post the code. Also it is interesting to post more information about the HTMLParser, including the lines that log the result below and anything that might be synchronizing the code. Just looking at the lines of code you posted doesn’t tell you much about the problem.

1 answer

3


In fact, it makes perfect sense:

List< IResult > result = future.get( ); // wait for a processor to complete

You’re calling get in each Future, which is bloating, thus making a sequential execution once the next getwill only be called when the current is finished running.

The API of Futureonly gives you the method isDone, which is not block and will return true if that computation is completed.

Instead of passing the Callableone by one you can use invokeAll:

List<Future<Whatever>> futures = pool.invokeAll(callables);

Then iterate on the calling Futures getwhen you know that it has already completed processing:

for(Future<List<Whatever>> f : futures) {
    if(f.isDone()) {
        f.get() // aqui você faz a mágica acontecer
    }
}

Finally, you don’t need to get stuck to the loop that checks isDone, you can periodically check the result.

  • At the end processing of all threads I want to return to the list that is the merge of thread lists, with this cycle "for" if one has not finished continues and then ends. This is ignore the ones that aren’t finished... How do I wait for all of them to end and in the end merge the lists of all threads ?

  • This solution if a thread has not finished its work on isDone the result is discarded...

  • Like I said, you don’t need to be stuck with for, You’ll need a different strategy. For example, store all that are not complete in a new list, wait a span of time and then check again.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.