我正在尝试通过重用可运行对象而不是为ThreadPool中的每个任务创建一个新对象来提高Dijkstra算法的效率。每个任务需要3个参数(开始值,结束值和CountDownLatch)。我尝试使用getters / setters,除了在线程类的run()方法中,它在任何地方都有效。它不断重复使用一个变量,这弄乱了算法]
这是线程类,run()执行一个方法来查找图中的下一个最近的节点。变量和获取器是全局的:
//Thread class
class ClosestNodeTask implements Runnable {
@Override
public void run() {
getNodeShortestDistanced(getStart(), getEnd(), getCdlClosest());
}
}
下面的代码段在apply()方法中执行。
创建对象(一次):
ClosestNodeTask closestNodeTask = new ClosestNodeTask();
此代码段提供了线程池要执行的任务:
for (int t = 0; t < numberOfThreads; t++) {
int start;
int end;
if (nodesModulo > 0 && numberOfThreads == (t + 1)) {
start = nodesPerThread * (t);
end = nodesPerThread * (t + 1) + nodesModulo;
setStart(start);
setEnd(end);
setCdlClosest(cdlClosest);
executor.execute(closestNodeTask);
} else {
start = nodesPerThread * t;
end = nodesPerThread * (t + 1);
setStart(start);
setEnd(end);
setCdlClosest(cdlClosest);
executor.execute(closestNodeTask);
}
}
'start'变量的输出有两个线程:0和12500。如果我在可运行对象的run()中执行getstart(),它将始终返回12500,从而弄乱了算法。如果我在其他任何地方都执行getstart(),则总会得到正确的输出0和12500。
我在做什么错?我不明白为什么run()方法不断重复使用相同的变量。
创建单个对象并在多个线程中使用它时,实际上是在与所有这些线程共享一个公共状态。也就是说,当您可以设置setStart()等时,您将为所有正在运行的线程以及正在创建的新线程设置开始。
每个线程需要单独的对象。这要么是您正在运行的类的单独实例的形式,要么是效率较低的线程局部变量。