0

I have one "Runnable" threads which is initiating few "Callable" threads and I want to display results when all above threads has finished their jobs.

What is the best way to do it?

My code is as follows

Connector.java (Starting Runnable Thread)

  public class Connector {
                      private static void anyFileConnector() {
                    // Starting searching Thread
                        ExecutorService executor = Executors.newFixedThreadPool(100);
                        executor.submit(traverse, executor);
//HERE I WANT MY ALL SEARCH RESULTS/OUTPUT : CURRENTLY IT IS STARTING OTHER THREADS AND NOT SHOWING ME ANY RESULTS BECAUSE NONE OF THEM WAS FINISHED.(IN CONSOLE, I WAS ABLE TO SEE RESULTS FROM ALL THE THREADS
        setSearchResult(traverse.getResult());

                    executor.shutdown();
            }
    }

Traverse.java (Runnable Thread) I am using ExecutorCompletionService to handle it...but it didn't create any difference. :(

public class Traverse implements Runnable {
    public void run() {

    ExecutorService executor = Executors.newFixedThreadPool(100);
    ExecutorCompletionService<List<ResultBean>> taskCompletionService =
            new ExecutorCompletionService<List<ResultBean>>(executor);
    try (DirectoryStream<Path> stream = Files
            .newDirectoryStream(dir)) {
                Search newSearch = new Search();
                taskCompletionService.submit(newSearch);
     }
    list.addAll(taskCompletionService.take().get());
    }
}

Search.java (Callable Thread)

public class Search implements Callable<List<ResultBean>> {
 public List<ResultBean> call() {
        synchronized (Search.class) {
// It will return results
            return this.search();
        }
    }

}
user1653773
  • 373
  • 1
  • 5
  • 18

3 Answers3

2

Go for CyclicBarrier and you will be able to achieve this. A cyclic barrier will perform a task as soon as all the threads are done with their work, this is where you can print the en result.

Check this lik for working of CyclicBarrier : http://javarevisited.blogspot.com/2012/07/cyclicbarrier-example-java-5-concurrency-tutorial.html

Lokesh
  • 7,810
  • 6
  • 48
  • 78
  • create an instance of CB like this : final CyclicBarrier cb = new CyclicBarrier(total thread count, new Runnable(){"your final Task"}); . Now pass reference of this cyclic barrier to all the threads and ensure that in each thread you call "barrier.await();". Thats it, as soon as all threads are done with their job, your final task will be executed. – Lokesh Aug 04 '13 at 14:34
  • in my case, i don't have any specific "thread count"..it can be any number as i am traversing a folder and searching for files there...So can i give some maximum number there?...or any other way to handle that? – user1653773 Aug 04 '13 at 14:39
  • Nope, you need to know total count before hand. What i would suggest is conduct your folder search before initializing CyclicBarrier that way you know total count of threads before hand itself. – Lokesh Aug 04 '13 at 14:52
  • i can't do that...i am traversing and searching together...means..once i got a file...i am starting a search thread...like this i m doing searching..in the end i want all the consolidated results..but i am not getting results in the end..because as soon as i click on "search"..it is just starting the threads (both traversing and searching) and comes into the end without any results (because others are still doing traversing and searching) – user1653773 Aug 04 '13 at 15:16
  • any idea??..how can i achieve it?? – user1653773 Aug 04 '13 at 15:38
  • Yours is a tricky situation, i need to think over but CyclicBarrier is the best api for such case. – Lokesh Aug 04 '13 at 15:43
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/34796/discussion-between-user1653773-and-loki) – user1653773 Aug 04 '13 at 15:56
1

Easy - all the Callables will return Future objects which you can used to wait and get the result by calling Future.get() in a blocking wait way. So your problem is just a for loop waiting for each future on the callables blockingly.

After that, just aggregate the results to return to client.

Alex Suo
  • 2,977
  • 1
  • 14
  • 22
1

The submit method of executor service can return a list of Future objects. What you can do for your case is call isDone() method of these Future objects in a while loop.

Whenever, any future task gets completed this method will return true. You can now call get() method on this to get the value returned by this task. In this way you could get hold of all the future task values without having to wait for any particular task to get complete (since your first future task could have the longest completion time)

Tushu
  • 1,866
  • 3
  • 14
  • 19