简体   繁体   中英

How can i know threads jobs are done?

In class B how can i know jobs of threads are finished? In after properties some worker are running. In class B, I need to know if worker are done?

public class A implements InitializingBean{
     public void method1(){
        ...
    }    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.print("test after properties set");      
        // send threads to executorService
        ExecutorService executorService = Executors
                .newFixedThreadPool(4);
        for (int i = 0; i < 4; i++) {
            Worker worker = new Worker();       
            executorService.submit(worker);
        }
    }
}
public class Worker implements Callable<Void>{
    @Override       
    public void call(){
     ...
   }
}
public class B{
   public void methodB(){
      A a = new A();
     a.method1();
     ///Here How can i know the job of the workers are finished?
   }
}

Use a listener/callback pattern to have the thread report completion to a listener. This simple example should show the process:

public interface ThreadCompleteListener {
    void workComplete();
}

public class NotifyingThread extends Thread {
    private Set<ThreadCompleteListener> listeners;
    // setter method(s) for adding/removing listeners to go here

    @Override
    public void run() {
        // do stuff
        notifyListeners();
    }

    private void notifyListeners() {
        for (ThreadCompleteListener listener : listeners) {
            listener.workComplete(); // notify the listening class
        }
    }
}

in your listening class:

NotifyingThread t = new NotifyingThread();
t.addListener(new ThreadCompleteListener() {
    void workComplete() {
        // do something
    }
});

t.start();

You could use a Future implementation for your thread. It provides a Future#isDone()

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#isDone()

In general, it is usually more useful to be notified via a callback when jobs complete. However, since others have posted answers which follow that model, I'll instead post a solution that simply allows you to poll and ask whether the jobs are finished, in case this is what fits the needs of your application better.

public static interface InitializingBean{
    public void afterPropertiesSet() throws Exception;
}

public static class A implements InitializingBean{

    private List<Future<Void>> submittedJobs = Collections.synchronizedList(new ArrayList<Future<Void>>());  

    public void method1(){
        //do stuff
    }    
    @Override
    public void afterPropertiesSet() throws Exception {
                    System.out.print("test after properties set");      
        // send threads to executorService
        ExecutorService executorService = Executors
                .newFixedThreadPool(4);
        synchronized (submittedJobs) {              
            for (int i = 0; i < 4; i++) {
                Worker worker = new Worker();       
                submittedJobs.add(executorService.submit(worker));
            }
        }
    }

    /**
     * Allows you to poll whether all jobs are finished or not.
     * @return
     */
    public boolean areAllJobsFinished(){
        synchronized (submittedJobs) {              
            for(Future<Void> task : submittedJobs){
                if(!task.isDone()){
                    return false;
                }
            }

            return true;
        }
    }
}
public static class Worker implements Callable<Void>{
    @Override       
    public Void call(){
     //do worker job

     return null; //to satisfy compiler that we're returning something.
   }
}
public static class B{
   public void methodB(){
      A a = new A();
     a.method1();

     if(a.areAllJobsFinished()){
         System.out.println("Congrats, everything is done!");
     } else {
         System.out.println("There's still some work being done :-(");
     }
   }
}

If you'd like to wait in that thread that starts the ExecutorService, you can actually use the awaitTermination method.

At the end of you afterPropertiesSet method, you should add:

executorService.shutdown();

After this you then add:

executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)

This causes the thread to wait for all the executorService's tasks to be done and then continues. So place any code you want to execute after the call to awaitTermination.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM