2
\$\begingroup\$

Scenario: I have a main thread which spawns few child threads to do some independent tasks. After each child thread finishes their tasks, the main thread proceeds. The code I have written is working in most of the time. However, in case one of child thread gets blocked, the main thread has to wait for ever. As it is not happening frequently, I am kind of OK as of now. But I am looking for a better solution

I am not trying to interrupt the child threads by waiting in main thread and then interrupting the child threads, because I don't know upfront how much time I need to wait for all the children to finish their tasks.However, it should not take more than 10 mins(worst case) for the children to finish their tasks. But if I go with thread interrupt way, I will have to wait for 10 mins always even if all children finishes their tasks in 2 mins itself. Lots of time (8 min here) will be wasted for nothing.

So, is it possible to review my code and suggest if any enhancement is possible?

Thread Class

public class MyThread implements Runnable{

@Override
public void run() {
    /*
     * Actual method do the following:
     * 1. Say we have 10 person. So, do the following for each person
     *   1.1 Fetch social network(FB,LN,TW etc )profiles 
     *   1.2 Process the profiles and store in database
     * 2. Finished
     */
    System.out.println("hello world by thread "+ Thread.currentThread().getName());     
  }
}

Invoker Class

public class ThreadInvoker {

public static void main(String[] args){

    List<Thread> threadList = getMyThreadList();        

    for (Thread thread : threadList) {
        thread.start();
    }

    System.out.println("Waiting for Child Threads to die");

    for (Thread thread : threadList) {
        try {
            thread.join();
            System.out.println(thread.getName() + " Finished its job");             
        } catch (InterruptedException e) {
            System.out.println("Interrupted Exception thrown by : "
                    + thread.getName());                
        }
    }

    System.out.println("All Child Threads Finished their Job");
}


/**
 * Dummy method to get a list of Threads. Content of this method may not be reviewed.
 * Actual method do some other way to return a list of threads
 * @return
 */
private static List<Thread> getMyThreadList() {
    List<Thread> threadList = new ArrayList<>();
    MyThread myThread;
    Thread thread;
    for(int i=0; i<10; i++){
        myThread = new MyThread();
        thread = new Thread(myThread);
        thread.setName("Thread "+i);
        threadList.add(thread);
    }
    return threadList;
 }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ observer-observable pattern maybe? I mean let the child threads notify the invoker class that they are finished. At that time, you could check how many are finished, your running time and make a decision if you interrupt who's left? You could even set a timer for timeout. The advantage is when all children are finished in 2 min, you don't need to wait the 8 extra minutes, only when 1 is blocking. \$\endgroup\$ – chillworld Nov 3 '15 at 8:14
  • 1
    \$\begingroup\$ Read up on CountDownLatch - docs.oracle.com/javase/7/docs/api/java/util/concurrent/… \$\endgroup\$ – VoiceOfUnreason Nov 3 '15 at 13:09
5
\$\begingroup\$

Instead of creating threads use an ExecutorService and use invokeAll(Collection<Callable>, long, timeUnit). This will return when all calls are done or the timeout expires whichever happens first. Tasks that aren't completed will be canceled (which can be checked by the isCanceled() property of the matching Future in the return value).

This will mean you will need to change the Runnables to Callables but that just means returning null in the call method.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.