如果另一个计时器事件被挂起,ScheduledThreadPoolExecutor计时器不会触发

时间:2016-09-14 10:38:09

标签: java threadpool

请考虑以下代码。

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
}
#container,
#container2 {
  width: 400px;
  height: 300px;
}
.main-image {
  width: 100%;
  height: 100%;
}
.main-image-bg {
  background: url(http://i2.cdn.turner.com/cnnnext/dam/assets/151009172735-02-tbt-bob-dylan-restricted-super-169.jpg) center center no-repeat;
  background-size: cover;
  width: 100%;
  height: 100%;
}
img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* This mages the image behave like background-image with background-size: cover */
}

有两个定时器按固定速率安排,在第一个定时器事件中,任务无限期挂起。

即使第一个任务挂起,我希望第二个计时器以指定的速率触发,因为它是使用允许创建任意数量线程的线程池创建的。

但是,第二个计时器永远不会发射。

有人可以解释原因吗?

1 个答案:

答案 0 :(得分:2)

来自ScheduledThreadPoolExecutor's javadoc的引言解释了我的猜测

  

虽然这个类继承自ThreadPoolExecutor,但是一些继承的调优方法对它没用。特别是,因为它使用corePoolSize线程和无界队列充当固定大小的池,所以对maximumPoolSize的调整没有任何有用的效果。此外,将corePoolSize设置为零或使用allowCoreThreadTimeOut几乎绝不是一个好主意,因为一旦它们有资格运行,这可能会使池没有线程来处理任务。

您错过的关键部分是ScheduledThreadPoolExecutor类是“固定大小的池,使用 corePoolSize 线程和无界队列”。因此,除了 corePoolSize 之外,它不会产生任何额外的线程。

如果你想知道为什么它实际上是用corePoolSize == 0执行的,那么这里是一个来自ThreadPoolExecutor的代码片段,它确保至少有一个线程(以及阻止在你的情况下启动更多线程的线程):

call order:  
1. java.util.concurrent.ScheduledThreadPoolExecutor#scheduleAtFixedRate 
2. java.util.concurrent.ScheduledThreadPoolExecutor#delayedExecute   
3. java.util.concurrent.ThreadPoolExecutor#ensurePrestart
            /**
             * Same as prestartCoreThread except arranges that at least one
             * thread is started even if corePoolSize is 0.
             */
            void ensurePrestart() {
                int wc = workerCountOf(ctl.get());
                if (wc < corePoolSize)
                    addWorker(null, true);
                else if (wc == 0) //here's your case
                    addWorker(null, false);
            }