1

I am still learning about using Future and Callable in Java. Stumble into this question:

Say I have class:

TaskWorker implements Callable {
  public String id;
  public TaskWorker(String id) {
     this.id = id;
  }

  public Documents call() trows Exception {
       //Assume here, that Search and Doc are my own method to search and retrieve docs
       Search search =  new Search();
       Documents docResult = search.process(id);

       //think about documents has getDocs
       //docResult.getDocs() will return number of document found from search

       return docResult;
  }
}

And here is the main method:

public static void main(String[] args) {
   //assume here, that I build in request contains many Id

   Request request = new Request();
   request.process;

   ExecutorService service = Executors.newFixedThreadPool(3);
   List<Future<Documents>> result = new ArrayList<Future<Documents>>();

   for (int i=0;i<request.length;i++) {
       Callable<Documents> worker = new TaskWorker(request.getId[i]);
       Future<Documents> submit = executor.submit(worker);
       result.add(submit);
   }

   Response response = new Response();
   ArrayList<Documents> docList = new ArrayList<Documents>();

   for (Future<Documents> future:result) {
     docList.add(future.get().getDocs());
   }

   response.setDocuments(docList);
}

What I am trying to do is, breaking a part the request to run in separate thread since each of the request Id is separate Search process. So I am trying to utilize Java pooling, by storing the result in the future object.

The thing I am confused is, how does future will work in this case? For each thread completion, is it going to hold the results? And after all the process finish, I can just loop future object to get the results right?

Also, there is no guarantee that process will run in order (1,2,3,4,etc), right? If that the case, then what is the best strategy if I want to associate each original request with the future result?

Please advise.

Thanks

Graham Griffiths
  • 2,196
  • 1
  • 12
  • 15
javaWorker
  • 35
  • 2
  • 4

2 Answers2

2

Also, there is no guarantee that process will run in order (1,2,3,4,etc), right? If that the case, then what is the best strategy if I want to associate each original request with the future result?

You cannot know the order in which the background threads are started and finished, but when you loop through your result-ArrayList you will get, of course, the results in the order you submitted them. The only thing that can happen here is that the .get() will block until the particular result of this future-object is available, if not already available.

bjoern.bauer
  • 699
  • 3
  • 6
  • Oh I see. Is there a reason to worry here about using Arraylist instead of Vector regarding thread safe issue? – javaWorker Oct 29 '10 at 15:41
  • Also, of course I forgot to shutdown ExecutorService. Assume, i need to put them after the future-loop, right? – javaWorker Oct 29 '10 at 15:41
  • 1
    You don't need to worry about thread-safety of the result-ArrayList because it is only accessed from one thread (the main thread) and not from any of the background threads. You should shutdown the ExecutorService after the future-loop. Otherwise your program won't exit until the executor terminated all cached background threads. – bjoern.bauer Oct 29 '10 at 15:59
0

You should create SynchronizedMap and pass it to TaskWorker in constructor together with a Request. TaskWorker should add Request and Result to the map when it finishes the job.

You dont have to loop Futures to get results, just make sure all jobs are finished.

Peter Knego
  • 79,991
  • 11
  • 123
  • 154