线程池中的时间分片算法

问题描述

首先让我们谈谈原始线程。说我有4个核心和6个线程。这四个内核将“时间片化”这六个线程。将全部时间都花在这四个核心上。

但是说我有4个线程的固定池,我在其中运行10个线程。我读到它将“查看”这10个线程作为任务。这意味着它不会在时间上划分10个线程,而是一次运行4个,一旦其中一个完成,就需要另一个,依此类推。

我有点困惑,为什么在第一种情况下需要切片,而在第二种情况下没有切片?但是从技术上讲可能存在(比如说我有4个内核,并且有5个线程池与这10个线程一起工作),那么这5个线程将​​被时间分割为这4个内核。同样,在5个线程中,我最多可以同时执行5个任务,直到完成一个任务为止。

我用很多思想写了这个。我在这里说错了吗?有人可以对我如何立即理解而又不加思索地制定基本的经验法则吗?我觉得我缺少基础知识。

解决方法

在第一种情况(4个内核和6个线程)中,将同时运行4个线程。 2个线程将在等待。
例如,如果线程1、2、3、4正在运行,而5、6正在等待,那么一段时间后,线程1、3、5、6正在运行,而2、4正在等待。
这就是时间分片的意思。

在第二种情况下,当您有4个工作线程的线程池时,同样的事情也会发生。
假设您提交了10个任务(Runnables),那么其中的4个任务肯定会立即运行; 6将在线程池队列中等待。
每当完成一项任务时,线程就会从队列中拉出另一个任务。
这将一直发生,直到队列中没有更多任务为止。
请注意,即使队列中没有任务,这四个工作线程仍处于活动状态,尽管处于睡眠状态(操作系统将从其他进程运行线程)。

如果所有任务都是100%受CPU限制的,则此线程池设计会更好,因为如果操作系统只有4个内核,那么无论有多少任务待处理,拥有4个以上的线程都是无用的。
通常,在同一系统中运行多个线程效率不高,因为上下文切换既昂贵又缓慢。

,

我有4个线程的固定池,我在其中运行10个线程。

通常您不要将Thread对象提交给ExecutorService,因为它会造成类似的混乱。

仅由于Thread类实现Runnable的事实,才可能将Thread对象提交给ExecutorService。 ExecutorService将把Thread对象与Runnable的任何其他实现一样对待:

当您将Thread对象提交到线程池时,该对象将添加到池的工作队列中。然后,池中的一个线程将其拾取,并直接调用Thread.run()方法,就像对Runnable的任何其他实例一样。

因此,Thread对象的run()方法在线程池的一个线程中运行,而不是在其自己的新线程中运行。永远不会调用Thread.start()方法来启动新线程。

这两个是等效的:

threadPool.submit(new Thread() {
    public void run() {
        doSomething();
    }
});

threadPool.submit(new Runnable() {
    public void run() {
        doSomething();
    }
});