首页 > 解决方案 > 如何让线程等到任务完成?

问题描述

我试图用 Java 编写一些线性代数库,并想使用 CPU 实现多线程。为此,我创建了一个ComputationMaster具有 8ComputationThread的类。

这个想法是,当任务被分配给主时,它将把这个任务交给所有线程,他们将继续工作。

我的尝试如下:

任务是在返回之前一直调用的方法false。该方法本身需要管理它正在工作的数据,但这不是问题本身的一部分。

public interface ComputationMethod {
    public boolean execute();
}

现在,让我们谈谈 ComputationThread:它扩展Thread并看起来像这样:

ComputationMethod computation;

public ComputationThread(){
    super();
    this.start();
}

public void run(){
    while(!this.isInterrupted()){
        try{
            if(computation != null){
                while(computation.execute()){}
                computation = null;
                ComputationMaster.notify_thread_finished();
            }
        }catch (Exception e){
            e.printStackTrace();
            this.interrupt();
        }
    }
    this.interrupt();
}

您可以看到它通知 ComputationMaster 他完成了任务,因为任务本身返回了false

最后,我将向您展示我的尝试ComputationMaster

public static final int MAX_THREAD_AMOUNT = 8;
public static Thread MAIN_THREAD;
private static ComputationThread[] threads = new ComputationThread[MAX_THREAD_AMOUNT];


static int finished = 0;
static synchronized void notify_thread_finished(){
    finished ++;
    if(finished == MAX_THREAD_AMOUNT){
        MAIN_THREAD.notifyAll();
        finished = 0;
    }
}
public static void compute(ComputationMethod method){
    for(ComputationThread t:threads){
        t.computation = method;
    }

    MAIN_THREAD = Thread.currentThread();
    try {
        MAIN_THREAD.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

这个想法是,当ComputationMasterget 是一种计算方法时,它将把它交给所有线程并等待它们完成。我还没有处理等待线程,所以我尝试保存当前线程并让它继续,一旦完成线程的计数器等于总线程的数量。

这对我来说似乎很合乎逻辑,但我的代码存在多个问题:

  1. 一个IllegalMonitorStateException被抛出。
  2. 假设任务已经完成,ComputationThreads将进入无限循环并等待直到给出新任务。(也许这也可以让他们等待)

我不想每次给出新任务时都创建一个新线程,并在任务完成后销毁它们。

标签: javamultithreading

解决方案


我认为您不需要线程之间的所有信号。你可以只使用 thread.join

此外,一个小的设计缺陷是,在设置成员之前,线程处于无限旋转循环computation中。这会稍微降低您的初始性能。您应该computation在启动线程之前设置成员。也就是说,不要让ComputationThreadinvoke的构造函数thread.start。在你的compute函数中这样做。

这可能是您所寻求的:

public static void compute(ComputationMethod method){
    for(ComputationThread t:threads){
        t.computation = method;
        t.start();
    }

    // wait for all threads to finish
    for(ComputationThread t:threads){
        t.join();
    }
}

然后你的运行功能被简化为:

public void run(){

   try {
       while(computation.execute()){}
   }
   catch (Exception e){
        e.printStackTrace();
   }
}

推荐阅读