线程池重用线程

Threadpool re-use of threads

我知道这个话题已经被问了很多,但我不确定一个细节。 现在线程池不会让线程在完成任务后死亡,并在以后根据需要重用它(正如所说 here, here,等等) 但是假设我的 运行nable 在构造函数中有变量 -

MyRunnable(int a){
  this.a = a; 
}

然后,当我们尝试使用 Executors.newFixedThreadPool(或类似的东西)运行 Runnable 时,我们说

executor.execute(new MyRunnable(a)); // executor being Executors.newFixedThreadPool

现在,如果变量 'a' 在每次执行中都不同,Threadpool 以后真的可以重用它吗? 我真的不明白那是如何工作的,但我从未见过 'Threadpool reuses threads except...',因此很困惑。

所以,从我的角度来看,线程池工作算法是如何相似的,如下所示

while (check if the pool is not shutdown) {
    Runnable task = pool.fetchTaskFromQueue(); // fetch the Task from the queue. In your case it object of MyRunnable class
    task.run(); // call the run() of MyRunnable object
}

线程池重新执行 Thread,而不是 Runnable/ Callable 实现。因此,根据线程池,它确实重用了您的 variable a.

不,您提交的 Runnable 以及与之相关的变量都不会被重复使用。

我想你误解了ThreadRunnable,它们是不同的东西。 Runnable 只是普通对象,除了它的 run 方法将在您使用它创建新线程时执行。您可以查看 this question

线程的复用不等于Runnable的复用,而是线程一直在执行不同的Runnables.


当您使用 Runnable 创建 Threadstart 时,此线程如下所示:

new Thread(new Runnable()).start()

这个Runnalerun()方法会被执行,run()退出后,这个Thread也会终止

但是,您提交给 ThreadPoolExecutorRunnbale 不是上面构造线程的代码。


简而言之,ThreadPoolExecutor 中的线程是这样创建的:

Runnable worker = new Runnable() {

    @Override
    public void run() {
        Runnable firstTask = getFirstTask();  // the first runnable 
        firstTask.run();

        Runnable queuedTask;
        while ( (queuedTask = getTaskFromQueue()) != null) {  // This could get blocked 
            queuedTask.run();
        }
    }
};
new Thread(worker).start();

请注意,用于启动线程的 Runnable 不是您提交到池中的线程。


当你提交新的Runnable时,线程池会检查是否需要创建新的线程(基于像corePoolSize这样的参数)。

  • 如果有必要,那么它会用这个Runnable创建一个新的Worker作为FirstTask,并用这个Worker创建一个新线程并启动它。
  • 如果没有,则将 Runnbale 放入队列中。当有空闲线程时,他们会检查这个队列并从中取任务。