Java 线程池中的时间切片算法
首先,让我们讨论原始线程。假设我有4个内核和6个线程。这4个内核将对这6个线程进行“时间切片”。给这4个核心一点时间 但假设我有固定的4个线程池,我在其中运行10个线程。我读到它会将这10个线程视为任务。这意味着它不会对10个线程进行时间切片,而是一次运行4个线程,一旦其中一个线程完成,就会需要另一个线程,以此类推 我有点困惑,为什么在第一种情况下有时间切片,而在第二种情况下没有?但从技术上讲,可能会有(假设我有4个内核和5个线程池,可以处理这10个线程),然后这5个线程将在这4个内核中进行时间切片。另外,在5个线程中,最多可以同时执行5个任务,直到一个线程完成,然后再执行下一个线程 我写这篇文章时深思熟虑。我说错话了吗?有人能给我一个基本的经验法则,告诉我如何在不过度思考的情况下立即理解这一点吗?我觉得我缺少了一些基础知识。在第一种情况下(4个内核和6个线程),4个线程将同时运行。2个线程将等待。Java 线程池中的时间切片算法,java,multithreading,threadpool,cpu-cores,Java,Multithreading,Threadpool,Cpu Cores,首先,让我们讨论原始线程。假设我有4个内核和6个线程。这4个内核将对这6个线程进行“时间切片”。给这4个核心一点时间 但假设我有固定的4个线程池,我在其中运行10个线程。我读到它会将这10个线程视为任务。这意味着它不会对10个线程进行时间切片,而是一次运行4个线程,一旦其中一个线程完成,就会需要另一个线程,以此类推 我有点困惑,为什么在第一种情况下有时间切片,而在第二种情况下没有?但从技术上讲,可能会有(假设我有4个内核和5个线程池,可以处理这10个线程),然后这5个线程将在这4个内核中进行时间
例如,如果线程1、2、3、4正在运行,而线程5、6正在等待,则可能在一段时间后,线程1、3、5、6正在运行,线程2、4正在等待。
这就是时间切片的含义 在第二种情况下,当您有一个包含4个工作线程的线程池时,同样的情况也会发生。
假设您提交了10个任务(可运行),那么其中4个任务肯定会同时运行;6将在线程池队列中等待。
每当任务完成时,线程都会从队列中提取另一个任务。
这将持续发生,直到队列中没有剩余的任务。
请注意,即使队列中没有任务,4个工作线程仍处于活动状态,尽管处于休眠状态(操作系统将运行来自其他进程的线程) 如果所有任务都是100%CPU限制的,那么线程池设计会更好,因为如果操作系统只有4个内核,那么无论有多少任务挂起,拥有4个以上的线程都是无用的。
一般来说,在同一个系统中运行多个线程是没有效率的,因为上下文切换既昂贵又缓慢 我有固定的4个线程池,我在那里运行,比如说10个线程 通常情况下,您不会将线程对象提交给ExecutorService,因为这样会造成混乱 只有由于
Thread
类实现了Runnable
,才有可能向ExecutorService提交线程对象。ExecutorService将把线程对象与Runnable的任何其他实现一样对待:
将线程对象提交到线程池时,它将添加到线程池的工作队列中。然后池中的一个线程将其拾取,并直接调用Thread.run()方法,就像对任何其他Runnable实例一样
因此,Thread对象的run()方法在线程池的一个线程中运行,而不是在它自己的新线程中运行。从未调用Thread.start()方法来启动新线程
这两个是等效的:
threadPool.submit(new Thread() {
public void run() {
doSomething();
}
});
threadPool.submit(new Runnable() {
public void run() {
doSomething();
}
});
不要将
Thread
对象与线程混淆。Thread
对象只有在调用其start
方法时才会映射到线程。如果将其作为任务传递给线程池,则线程
将被视为可运行
。不会为其创建线程,而是从现有线程之一执行其run
方法。如果您需要具体的解释,请包含一些代码。我不理解您在“原始线程”和“线程”之间所做的区分。我不明白你所说的“我有固定的4个线程池,在那里运行,比如说10个线程”是什么意思。您可以有4个线程,也可以有10个线程。它是一个或另一个,而不是两者。@StephenC我认为“我有4个线程的固定池,我在其中运行,比如说10个线程”意味着用4个线程构建一个新的固定线程池,但在其中提交10个Runnable
s(这里还要记住thread
是一个Runnable
)。非常感谢!谢谢你,乔尼!