从一次生产消费者的bug看看线程池如何增加线程 (3)

然后,将CODE-A的代码注释掉,神奇的事情就发生了,直接一发入魂

2021-01-17 16:32:49.539 [Time-limited test] INFO - Producer init start... 2021-01-17 16:32:49.562 [Time-limited test] INFO - we init all topic 2021-01-17 16:32:49.806 [Time-limited test] INFO - non-static invoke-------- ########## 2021-01-17 16:32:49.819 [Time-limited test] INFO - we init random1 topic 2021-01-17 16:32:49.819 [Time-limited test] INFO - non-static invoke-------- ########## 2021-01-17 16:32:49.819 [EVENT-CONSUMER-1] INFO - take event** ########## 2021-01-17 16:32:49.820 [EVENT-CONSUMER-2] INFO - take event** ########## 2021-01-17 16:32:49.821 [Time-limited test] INFO - we init random2 topic 2021-01-17 16:32:49.821 [Time-limited test] INFO - non-static invoke-------- 2021-01-17 16:32:49.824 [Time-limited test] INFO - we init random3 topic 2021-01-17 16:32:49.824 [Time-limited test] INFO - non-static invoke-------- 2021-01-17 16:32:49.826 [Time-limited test] INFO - we init random4 topic 2021-01-17 16:32:49.880 [Time-limited test] INFO - non-static invoke-------- 2021-01-17 16:32:49.884 [Time-limited test] INFO - Producer init end... 2021-01-17 16:32:49.884 [Time-limited test] INFO - publish start... 2021-01-17 16:32:49.884 [Time-limited test] INFO - publish over... 2021-01-17 16:32:49.885 [ **EVENT-PRODUCER-3** ] INFO - topic random1 queueSize 0 finish 0 ########## 2021-01-17 16:32:49.885 [Time-limited test] INFO - publish over... 2021-01-17 16:32:49.886 [EVENT-PRODUCER-3] INFO - from producer queue take a message random2 1 2021-01-17 16:32:49.886 [Time-limited test] INFO - publish start... 2021-01-17 16:32:49.886 [ **EVENT-PRODUCER-3** ] INFO - topic random2 queueSize 0 finish 0 ########## 2021-01-17 16:32:49.886 [Time-limited test] INFO - publish over... 2021-01-17 16:32:49.886 [EVENT-PRODUCER-3] INFO - from producer queue take a message random3 2 2021-01-17 16:32:49.886 [Time-limited test] INFO - publish start... 2021-01-17 16:32:49.886 [**EVENT-PRODUCER-3**] INFO - topic random3 queueSize 0 finish 0 ########## 2021-01-17 16:32:49.886 [Time-limited test] INFO - publish over... 2021-01-17 16:32:49.886 [EVENT-PRODUCER-3] INFO - from producer queue take a message random4 3 2021-01-17 16:32:49.886 [**EVENT-PRODUCER-3**] INFO - topic random4 queueSize 0 finish 0 ########## .... 2021-01-17 16:32:50.031 [EVENT-PRODUCER-3] INFO - topic random1 queueSize 27 finish 5 2021-01-17 16:32:50.031 [EVENT-PRODUCER-3] INFO - from producer queue take a message random2 129 2021-01-17 16:32:50.031 [EVENT-PRODUCER-3] INFO - topic random2 queueSize 32 finish 0 . . . 2021-01-17 16:32:50.275 [EVENT-CONSUMER-2] INFO - execute RandomSleepConfigListener 2021-01-17 16:32:50.283 [EVENT-CONSUMER-2] INFO - TOPIC[random1] size 4, remainingCapacity 28 finish 29 2021-01-17 16:32:50.283 [EVENT-CONSUMER-2] INFO - take event 2021-01-17 16:32:50.283 [EVENT-CONSUMER-2] INFO - execute RandomSleepConfigListener 2021-01-17 16:32:50.289 [EVENT-CONSUMER-2] INFO - TOPIC[random1] size 3, remainingCapacity 29 finish 30 2021-01-17 16:32:50.290 [EVENT-CONSUMER-2] INFO - take event 2021-01-17 16:32:50.290 [EVENT-CONSUMER-2] INFO - execute RandomSleepConfigListener 2021-01-17 16:32:50.299 [EVENT-CONSUMER-2] INFO - TOPIC[random1] size 2, remainingCapacity 30 finish 31 2021-01-17 16:32:50.299 [EVENT-CONSUMER-2] INFO - take event 2021-01-17 16:32:50.299 [EVENT-CONSUMER-2] INFO - execute RandomSleepConfigListener 2021-01-17 16:32:50.305 [EVENT-CONSUMER-2] INFO - TOPIC[random1] size 1, remainingCapacity 31 finish 32 2021-01-17 16:32:50.305 [EVENT-CONSUMER-2] INFO - take event 2021-01-17 16:32:50.306 [EVENT-CONSUMER-2] INFO - execute RandomSleepConfigListener 2021-01-17 16:32:50.315 [EVENT-CONSUMER-2] INFO - TOPIC[random1] size 0, remainingCapacity 32 finish 33 2021-01-17 16:32:50.316 [EVENT-CONSUMER-2] INFO - take event

看日志是只有topic1被消费了,其他的topic都没有被消费。

第一段和第二段表明,生产者是如期按照我们设想的,逐个将详细进行分发,我的测试程序是按顺序进行1~4的消息分发的。

EVENT-CONSUMER的线程编号只有到2,3是属于生产者线程的编号。于是我就感觉很奇怪,为什么线程池没有继续创建线程呢?

3 分析原因

我开始去查看了线程池execute()这个方法

public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running, try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount, and so prevents false alarms that would add * threads when it shouldn't, by returning false. * * 2. If a task can be successfully queued, then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped, or start a new thread if there are none. * * 3. If we cannot queue task, then we try to add a new * thread. If it fails, we know we are shut down or saturated * and so reject the task. */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) // ------------ debug后发现进入到这里条件无法满足 addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxpfs.html