java - 如何让线程等到任务完成?
问题描述
我试图用 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();
}
}
这个想法是,当ComputationMaster
get 是一种计算方法时,它将把它交给所有线程并等待它们完成。我还没有处理等待线程,所以我尝试保存当前线程并让它继续,一旦完成线程的计数器等于总线程的数量。
这对我来说似乎很合乎逻辑,但我的代码存在多个问题:
- 一个
IllegalMonitorStateException
被抛出。 - 假设任务已经完成,
ComputationThreads
将进入无限循环并等待直到给出新任务。(也许这也可以让他们等待)
我不想每次给出新任务时都创建一个新线程,并在任务完成后销毁它们。
解决方案
我认为您不需要线程之间的所有信号。你可以只使用 thread.join
此外,一个小的设计缺陷是,在设置成员之前,线程处于无限旋转循环computation
中。这会稍微降低您的初始性能。您应该computation
在启动线程之前设置成员。也就是说,不要让ComputationThread
invoke的构造函数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();
}
}
推荐阅读
- javascript - 使用javascript将带有类名的span添加到字符串的某些字符
- c++ - val1, val2, val3, val4 的值是如何计算的?
- ios - 如何从父 ViewController 继承 @IBOutlets?
- julia - 如何在 Julia 中将两个地块相邻放置?
- kubernetes - K8s CRD 错误:不支持的媒体类型 415
- android - Viewmodel 在第一次之后不会更改 Livedata
- c# - 来自字符串的 C# 条件,包括运算符
- node.js - 如何保持帐户会话登录?
- javascript - 如何从反应导航更改底部材质选项卡导航器的高度
- c++ - 用户定义类型的隐式类型转换