How to use ExecutorService of java concurrent programming?

7k views Asked by At

Iam using below code for uploading images on the remote server.When I use below it is uploading all images cocurrently on remote server.

List<Future<String>> futureList = new ArrayList<Future<String>>();
ExecutorService execService = Executors.newFixedThreadPool(Images.size());
for (IImage image : Images) { 
  try {
    //execService.execute(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
    singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
    //Log.d("","singleFuture -------"+singleFuture.get());
    futureList.add(singleFuture);
    Log.d("","futureList Size:"+futureList.size());
  } catch(Exception e){
    execService.shutdown();
  }

Whenever i used below code

   singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
//Log.d("","singleFuture -------"+singleFuture.get());
    futureList.add(singleFuture);

adds all the future objects to futurelist immediately returning from runnable(not waiting in runnable until completion of uploading of all images(background uploading processing is going)

But whenever i uncommented below line in above code ,after successful uploading of every image it returns from runnable.

singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
Log.d("","singleFuture -------"+singleFuture.get());
futureList.add(singleFuture);

is there anything wrong in my code and is it ok to take remote server connection more at a time or any load is on server?How to upload the images by using cocurrent programming java?Please give us guidance?

Do the submit() and execute() functions have the same effect?

2

There are 2 answers

1
fmucar On BEST ANSWER

When you call singleFuture.get() you are waiting for the operation to complete. So the loop won't continue to execute next statement until this one returns a result.

You need to submit your tasks in the first loop and after that, another loop should iterate over the results future.get() on your list to make it async

From @andersoj's answer;

The Pool size should be something related to your CPU cores. Not the number of images you have in hand. Say if you have 2 cored CPU, a coefficient of 5 (just my guess of coefficient) for image uploading io time.

POOL_SIZE = NUM_OF_CPU_CORE*coeffiecient;

7
andersoj On

submit() adds a task to the queue and returns a Future. execute() does not return a Future. See also here. Different orderings you observe may occur as side-effects of the additional management that happens inside submit() and probably are irrelevant. (But see @fmucar's answer...)

Not sure precisely what your question is...

It doesn't really make sense to size your thread pool based on the number of images you want to upload -- probably some small number of threads is sufficient, since you're just trying to keep some TCP streams fed. One thread per image, if the list of images is large, won't buy you anything.

If you are collecting Futures only to know when the uploads complete, consider one of the following:

Edited to add: Good catch, @fmucar, the call to .get() in the logger line forces sequentiality, so the thread pool is a waste.

invokeAll() example

Here's an attempt to give you an invokeAll() example; not sure if it quite matches your code.

final int poolSize = ...;  // see fmucar's answer
final ExecutorService execService = Executors.newFixedThreadPool(poolSize);
final List<Callable<>> uploadTasks = new ArrayList<Callable<>>();

for (final IImage image : Images) { 
   // maybe I got this wrong?  Can't quite parse your code.
   Callable<String> uTask = new uploadImages(image.getDataPath(),image.getDisplayName());
   uploadTasks.add(uTask);
}
// this thread will block here until all the tasks complete
final List<Future<String>> futureList = execService.invokeAll();
// or you can toss the result entirely if the futures don't matter.