Java线程池重用可运行对象,而不是为每个任务创建新对象

Java线程池重用可运行对象,而不是为每个任务创建新对象,java,concurrency,threadpool,runnable,dijkstra,Java,Concurrency,Threadpool,Runnable,Dijkstra,我试图通过重用runnable对象,而不是为线程池中的每个任务创建一个新的对象,来提高Dijkstra算法的效率。每个任务需要3个参数(开始值、结束值和倒计时锁存)。我尝试使用getter/setter,除了在thread类的run()方法中,这在任何地方都有效。它不断地重复使用一个变量,这就把算法搞砸了 这是thread类,run()执行一个方法来查找图中下一个最近的节点。变量和getter是全局的: //Thread class class ClosestNodeTask i

我试图通过重用runnable对象,而不是为线程池中的每个任务创建一个新的对象,来提高Dijkstra算法的效率。每个任务需要3个参数(开始值、结束值和倒计时锁存)。我尝试使用getter/setter,除了在thread类的run()方法中,这在任何地方都有效。它不断地重复使用一个变量,这就把算法搞砸了

这是thread类,run()执行一个方法来查找图中下一个最近的节点。变量和getter是全局的:

//Thread class
        class ClosestNodeTask implements Runnable {

            @Override
            public void run() {
                getNodeShortestDistanced(getStart(), getEnd(), getCdlClosest());
            }
        }
下面的代码段在apply()方法中执行

创建对象(一次):

此代码段提供线程池要执行的任务:

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);
    }
}
for(int t=0;t0&&numberOfThreads==(t+1)){
start=nodesPerThread*(t);
end=nodesPerThread*(t+1)+nodesModulo;
设置启动(启动);
setEnd(end);
设置cdlClosest(cdlClosest);
执行者。执行(关闭节点任务);
}否则{
start=nodesPerThread*t;
end=nodesPerThread*(t+1);
设置启动(启动);
setEnd(end);
设置cdlClosest(cdlClosest);
执行者。执行(关闭节点任务);
}
}
“start”变量的输出有两个线程:0和12500。如果我在runnable对象的run()中执行getstart(),它总是返回12500,从而打乱了算法。如果我在其他地方执行getstart(),我总是得到正确的输出0和12500


我做错了什么?我不明白为什么run()方法总是重复使用同一个变量

当您创建一个对象并在多个线程中使用它时,您实际上与所有这些线程共享一个公共状态。也就是说,当您可以设置start()等时,您将为所有正在运行的线程以及正在创建的新线程设置开始


每个线程都需要单独的对象。这要么是以正在运行的类的单独实例的形式,要么是以线程局部变量的形式,效率较低。

换句话说,您无法按照所描述的方式优化代码,因为这样做会引入与您发现的错误完全相同的错误。您已经在一开始就指出了您做错的地方:“我正试图通过重用可运行对象来提高Dijkstra算法的效率”。当您重用对象时,算法不会变得更有效。当“每个任务需要3个参数”时,您必须为每个任务创建一个包含3个参数的对象,这是一件基本且琐碎的事情。
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);
    }
}