52

我的多线程概念很弱,正在努力学习。

在 Java 中,我所知道的是,我们不能多次调用一个线程:

Thread t = new Thread; //Some Runnable
t.start();

t.start(); //Illegal and throw Exception at runtime.

据我所知,当您t.start()再次调用时它会引发异常,因为线程的关联堆栈一旦超出run()方法就会被破坏并且您正在尝试再次初始化事物。

在这种情况下,我对线程池的了解是,它可以提供更好的性能并节省时间,因为不需要创建新线程(我在阅读)。

如果在线程池场景中不需要创建新线程,那么它如何与刚刚完成其运行方法的同一线程一起工作,该线程是否可以再次使用?

我读到这个,它说“ java.util.concurrent 中的大多数执行器实现都使用线程池,它由工作线程组成。这种线程与它执行的 Runnable 和 Callable 任务分开存在,并且通常用于执行多项任务。

那么这里的 Worker 线程是什么,它与普通的 Java 线程有什么不同吗?

通过这个链接,我得到了一些东西,但仍然对使用线程池时可以消除哪些东西以及为什么它比使用普通 java 线程提供更好的性能感到困惑。

所以我们可以这样说,

线程分为三个部分,

  1. 创建(告诉操作系统它是新线程,为它创建堆栈。)
  2. 使用 run() 方法执行 Runnable。
  3. 销毁线程。

因此,考虑到上述 3 个步骤,在创建固定数量的线程后,可以消除线程池第 1 步和第 3 步。每个任务只会执行第 2 步,这就是为什么线程池更快?我们可以这样说吗?我对么?

4

4 回答 4

39

如果在 ThreadPool 场景中不需要创建新的线程,那么它如何与刚刚完成其运行方法的同一个线程一起工作,该线程是否可以再次使用?

简单 - 原始线程从未真正完成。它只是等待另一个任务执行。在伪代码中:

// No, this isn't even slightly accurate! General impression only :)
while (!pool.isShutdown()) {
    Runnable task = pool.waitForTaskOnQueue();
    task.run();
}

(很明显,当线程池关闭时,它也需要停止等待线程等待另一个任务 - 但希望你能明白一般的想法。)

于 2013-11-04T10:37:54.190 回答
5

该过程分为两个部分:

提交任务:线程池与阻塞队列紧密耦合。当我们说 executor.execute(runnable)。可运行/可调用在队列中排队。

任务的执行:现在需要从队列中提取任务。可以说,每当在队列中提交任务时,都必须将其拾取并执行。

所以有些线程将运行无限循环并监视任务队列。一旦任务可用,一个线程就会选择它并执行。

于 2016-02-27T14:32:53.957 回答
2

在线程池中,当新任务到达时,线程池不会创建新线程,而是保留许多空闲线程,以便根据需要执行任务。线程完成任务执行后,它不会死亡。相反,它在池中保持空闲状态,等待被选择执行新任务。

您可以限制池中一定数量的并发线程,这对于防止过载很有用。如果所有线程都在忙于执行任务,则将新任务放入队列中,等待线程变为可用

于 2017-07-19T04:26:02.827 回答
1

因此,考虑到以上 3 个步骤,使用 Threadpool 的第 1 步和第 3 步可以在固定数量的线程创建后消除。每个任务只会执行第 2 步,这就是为什么 Threadpool 更快?我们可以这样说吗?我对么?

是的,你是对的。线程创建和销毁是一项代价高昂的任务。由于在线程池中已经创建了线程,因此不存在线程创建的开销。但是,如果您的线程数比应有的多得多,那对您的应用程序将非常不利。它可能会OutofMemorry或可能会涉及其他一些问题。因此,要修复线程池大小,请使用以下公式:

no of threads = 2 * no_of_cores * no_of_disks * percentage CPU utilization you need * (1 + (W/ C))

(W/C) 是表示等待时间到计算时间的分数。

于 2013-11-04T14:58:51.493 回答