这是我在学校的操作系统课程中学习线程(理论上是嘿)之后的第一次多线程尝试,我认为我做我想做的事情的方式是糟糕的做法/草率
我正在通过为算法设置为运行的游戏的每个分支生成一个单独的线程来并行化minimax算法。调度部分有点棘手;随着算法迭代加深,我希望所有线程都有深度一致性。
所以,首先我有一个主线程,为游戏中的每个可用移动产生一个子线程:
public void run(){
// initializes all the threads
for (AlphaBetaMultiThread t : threadList) {
t.start();
}
try { //This won't ever happen; the subthreads run forever
evals = 0;
for (AlphaBetaMultiThread t : threadList) {
t.join();
evals += t.evals;
}
} catch (Exception e) {
System.out.println("Error joining threads: " + e);
}
}
线程将自己传递给构造函数,因此每个子线程都可以访问主线程的maxDepth属性和signalDepth方法:
public synchronized void signalDepth(){
signals++;
if (signals % threadList.length() == 0){
if (verbose)
System.out.println(toString());
depth++;
}
}
最后,这是子线程评估过程。每当它超过其余线程时,它会降低自己的优先级,然后产生直到所有子线程都发出信号。
public void run() {
startTime = System.currentTimeMillis();
while(true){
if (depth >= master.maxDepth) {
this.setPriority(4);
this.yield();
break;
} else {
this.setPriority(5);
}
eval = -1*alphabeta(0, infHolder.MIN, infHolder.MAX);
manager.signalDepth();
depth += 1;
}
}
除了我的实现似乎现在不能正常工作(仍然试图找出原因)之外,我真的觉得我正在做的事情并不是标准的做事方式。我的直觉是,可能有各种各样的内置多线程库可以让我的生活变得更轻松,但我真的不知道我在寻找什么。
哦,我也收到一条警告,说Thread.destroy()已被弃用(这是我计划在计算机播放器最终移动后摧毁所有内容的方式)。
我想我的问题是:我应该用什么来管理我的子线程?
编辑:哦,如果我遗漏了与我的问题相关的内容,请随时在github上查看我的完整代码:https://github.com/cowpig/MagneticCave 相关文件是GameThread和AlphaBetaMultiThread。 我为自己的无知而道歉!
另一个编辑:我希望线程永远迭代加深,直到gamePlayer对象(创建主线程的对象)决定是时候选择一个移动 - 它将访问移动列表并找到一个移动评价最高。这意味着.join()将不起作用,除非我为每个深度迭代创建一组新的线程,但那将需要更多的开销(我认为)所以我真的不想这样做。
答案 0 :(得分:3)
你的直觉是正确的。 Java 5引入了一系列有用的并发结构。您可能想要研究的是CyclicBarrier。它是一种同步辅助工具,允许多个线程相互等待以达到一个共同的障碍点(在您的情况下,这将是主深度)。
答案 1 :(得分:1)
你应该使用Thread.join()来等待子线程,这些子线程应该在完成时退出。根本不需要Thread.destroy(),也不需要摆弄优先级。
答案 2 :(得分:0)
您应该向ExecutorService
提交Thread
个实例,而不是使用原始Runnable
个实例的集合。如果您的所有主题都是某种计算结果,那么您可能希望使用Callable<?>
和ExecutorCompletionService
。
如果您有Runnable
的依赖关系图,我建议您使用优秀的Guava库中的ListenableFuture
。有关详细信息,请参阅ListenableFuture
explained wiki文章。
答案 3 :(得分:0)
如果dataflow graph表示适合您的任务,您可以使用我的数据流库df4j。