How can i know threads jobs are done?

时间:2015-07-31 19:50:18

标签: java multithreading

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?
   }
}

4 个答案:

答案 0 :(得分:4)

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();

答案 1 :(得分:3)

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()

答案 2 :(得分:2)

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 :-(");
     }
   }
}

答案 3 :(得分:0)

如果您想在启动ExecutorService的线程中等待,您实际上可以使用awaitTermination方法。

在afterPropertiesSet方法结束时,您应该添加:

executorService.shutdown();

然后再添加:

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

这会导致线程等待所有executorService的任务完成,然后继续。因此,在调用awaitTermination之后,请放置要执行的任何代码。