如何知道线程任务已完成?

5

在B类中,我如何知道线程的工作是否完成?在属性之后,有一些工作正在运行。在B类中,我需要知道工作是否完成。

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

你可以将日志或任何警告消息放在线程的末尾... - Bhagwat K
你可以实现一个回调接口,线程会调用其中的方法,通知任何监听器工作已完成。类似于JavaFX应用程序中Service所做的。你可以在想要监听完成的类中实现此接口,当线程完成工作时,它将调用该方法。 - Ryan J
您可以使用监听器/回调模式,当线程任务完成时通知已注册的监听器。 - ControlAltDel
你想知道所有的工作是否都完成了,还是每个工作何时结束? - augray
afterPropertiesSet不应该被用来启动执行器服务。这听起来很奇怪。而且,只有在Spring AppContext中使用Class A时才会调用afterPropertiesSet。 - aglassman
如果你只是想确保在一切准备就绪之前不执行 method1,可以让它抛出一个异常。 - Fildor
4个回答

4

使用监听器/回调模式,让线程向监听器报告完成。这个简单的例子应该展示了这个过程:

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

在你的听力课堂上:

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

t.start();

3

2

通常情况下,当作业完成时,通过回调通知更加有用。然而,由于其他人已经发布了遵循该模型的答案,因此我将发布一种解决方案,它简单地允许您轮询并询问作业是否已完成,以便更好地满足您的应用需求。

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

由于我忘记了将作业添加到提交的作业列表中的关键部分,因此我编辑了代码。 - augray

0

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

在您的 afterPropertiesSet 方法结束时,应添加以下内容:

executorService.shutdown();

接着,您再添加:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接