Java 创建新线程时执行(Runnable命令)

Java 创建新线程时执行(Runnable命令),java,multithreading,threadpoolexecutor,Java,Multithreading,Threadpoolexecutor,我正在阅读ThreadPoolExecutor.java的源代码,了解下面的execute方法: public void execute(Runnable命令){ 如果(命令==null) 抛出新的NullPointerException(); /* *分三步进行: * *1.如果运行的线程少于corePoolSize,请尝试 *以给定命令作为第一个线程启动新线程 *对addWorker的调用以原子方式检查运行状态和 *workerCount,从而防止可能增加 *在不应该的情况下,通过返回fal

我正在阅读
ThreadPoolExecutor.java
的源代码,了解下面的
execute
方法:

public void execute(Runnable命令){
如果(命令==null)
抛出新的NullPointerException();
/*
*分三步进行:
*
*1.如果运行的线程少于corePoolSize,请尝试
*以给定命令作为第一个线程启动新线程
*对addWorker的调用以原子方式检查运行状态和
*workerCount,从而防止可能增加
*在不应该的情况下,通过返回false执行线程。
*
*2.如果任务可以成功排队,那么我们仍然需要
*再次检查是否应该添加线程
*(因为自上次检查以来,已有的已死亡)或
*自进入此方法后,池关闭。因此
*重新检查状态,如有必要,在以下情况下回滚排队
*已停止,如果没有线程,则启动新线程。
*
*3.如果无法对任务排队,则尝试添加新任务
*线程。如果它失败,我们知道我们已关闭或饱和
*所以拒绝这个任务。
*/
int c=ctl.get();
if(工作计数(c)
假设线程池有2个核心线程,并将最大池大小设置为4

我可以理解代码
if(workerCountOf(c)
,这意味着如果当前核心线程计数小于核心轮询大小,只需创建一个新线程来处理runnable命令

我无法理解的是,如果我们已经调用了两次
execute(runnable)
,并且每个调用都需要很长时间才能完成,那么它们现在仍然很忙,现在我们正在调用第三次

代码将做什么?我想代码会转到
if(isRunning(c)&&workQueue.offer(command)){
所以命令会被添加到工作队列中。但是,我不明白这第三个命令将由哪个线程执行。根据代码
else if(workerCountOf(revecheck)==0)
,我认为工人数量应该是2,因为我们已经增加了两名工人

所以我的问题是第三个工人什么时候会被添加

--编辑--

我的测试代码:


public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,
                4,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(4)
        );

        threadPoolExecutor.execute(new Command("A"));
        threadPoolExecutor.execute(new Command("B"));
        threadPoolExecutor.execute(new Command("C"));

    }

    static class Command implements Runnable {
        private String task;
        Command(String task) {
            this.task = task;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000 * 10);
                System.out.println(new Date() + " - " + Thread.currentThread().getName() + " : " + task);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

对于测试代码,我预计核心工作人员将持续忙碌10秒,因此当
execute(“C”)
我想点击“核心工作人员正在忙碌,第三个工作人员将被添加”的案例,但似乎没有第三个工作人员?对不起,出了什么问题

谢谢

我想谈谈“核心员工很忙,将添加第三名员工”的案例

然后你还得把队列排满

Javadoc说:

在方法execute(java.lang.Runnable)中提交新任务时,并且运行的线程少于corePoolSize,则创建一个新线程来处理请求,即使其他工作线程处于空闲状态。如果运行的线程多于corePoolSize,但少于maximumPoolSize,则仅当队列已满时才会创建一个新线程

假设

   N = no of thread in currently in the pool.
   C = core size of pool
   M = maximum size of pool.
   BQ = Bounded Blocking Queue.(having a predefined capacity).
   UQ = Unbounded Blocking Queue.(without a predefined capacity).
   DHQ = Direct hand-offs Queue.
然后

1.如果是BQ

A.如果N“代码将做什么?”我认为调试器比我们更能解释它…@AndrewTobilko是的,我正在努力now@AndrewTobilko使用调试器调试线程调度代码非常困难。海森堡效应非常严重。只有在现有两个工作线程仍然忙的情况下,才会添加第三个工作线程。否则,其中一个工作线程将接管任务。@Thilo感谢您指出
 我想我可以理解核心工作线程从工作队列获取工作有一个循环,所以
workQueue.offer(命令)
将启动其中一个,它们将处理runnable。但是,通过阅读代码,我仍然无法理解何时/如何添加第三个辅助进程。谢谢。
threadPoolExecutor.execute(新命令(“A”);threadPoolExecutor.execute(新命令(“B”);threadPoolExecutor.execute(新命令(“C”));threadPoolExecutor.execute(新命令(“D”);threadPoolExecutor.execute(新命令(“E”);threadPoolExecutor.execute(新命令(“F”);threadPoolExecutor.execute(新命令(“G”));
这将命中创建第三个工作线程的案例。A/B不会添加到工作队列。C/D/E/F填充工作队列,因此在执行G时,它命中逻辑
否则如果(!addWorker(command,false))
。我不得不说,我还以为它会先增加工人,然后排队。但显然不是。你会一直保持核心工人的规模,直到你不能再排队为止。
   N = no of thread in currently in the pool.
   C = core size of pool
   M = maximum size of pool.
   BQ = Bounded Blocking Queue.(having a predefined capacity).
   UQ = Unbounded Blocking Queue.(without a predefined capacity).
   DHQ = Direct hand-offs Queue.
       1. If BQ

           A. If N <= C , then thread always created when task is submitted, idle 
              thread is  present in pool or not doesn't matter.
           B. Once the core pool size is reached, executor start puting 
              the new task in queue if there is no idle thread. 
              If there is any idle thread then the task is assigned to idle thread.
           C. When BQ is full, then executor start creating again new thread till 
              its value reached to M if there is no idle thread.
              So the new thread creation after reaching N=C value is start when queue 
              is full.
           D. Once N=M reached and BQ is also full , then executor not accept any 
              task.It throw exception.

      2. If UQ 

           A. Same as above
           B. Same as above
           C. Not applicable. Why ? because it is unbounded queue.
              (UQ capacity is Integer.MAX_VALUE)
           D. No effect of M. Why ? 
              Since creation of new thread again is start after the queue is full,but 
              in the case UQ queue is never full. 
              So new thread never created once reach N=C for the new task submitted. 
              Means thread in thread pool always be equal to C (N=C always) in case 
              UQ , whatever the value of M


     3. If DHQ 
          A. The direct hand-offs queue never put the task in queue, its immediately
             assigned task to thread if any thread is idle ,if not then it create new 
             one.(task in queue is always 0)
          B. The concept of C is not applicable in this queue.Thread created till 
             its value reach M.
          C. Once the N value reach M (N=M), and try to submit the task ,it reject 
             the task.