问题描述
我有一个来自Oracle网站的Scheduled Executor Service的示例代码。它创建一个scheduledexecutorservice,其核心池大小为1。它执行2个工作:首先,它启动以固定间隔执行的重复任务,然后在延迟后杀死同一任务和服务本身。
scheduledexecutorservice scheduledService = Executors.newScheduledThreadPool(1);
//This will keep executing the task at fixed interval
ScheduledFuture<?> futureTask = scheduledService.scheduleAtFixedrate(new RepeatedTask(),initialDelay,interval,TimeUnit.SECONDS);
//A future task is returned which can be used to cancel the execution after sometime
//Here we will cancel our repeated task after 100 seconds
scheduledService.schedule(new TaskStopper(futureTask,scheduledService),100,TimeUnit.SECONDS);
重复的任务代码:
public class RepeatedTask implements Runnable{
int count = 0;
@Override
public void run() {
count++;
System.out.println(count + ". Beep");
}
}
停止任务
@Override
public void run() {
mFutureTask.cancel(true);
System.out.println("Task stopped");
mExecutorService.shutdownNow();
boolean shutDown = mExecutorService.isShutdown();
if(shutDown) {
System.out.println("Executor shutdown");
}else {
System.out.println("Executor not shutdown");
}
}
我想了解一下,它如何与线程池中的单个线程一起工作。 由于我们的执行器服务执行两项任务并几乎同时启动两项任务, 我们不应该有2个线程,即scheduledexecutorservice的核心池大小为2。
虽然工作正常。我只想了解为什么它在单个线程中可以正常工作。
解决方法
对于任何线程池(包括ScheduledThreadPool),线程数可以少于任务数。线程池内部有一个任务队列,如果没有可用的线程来执行任务,则任务必须等待。
在您的示例中,在t = 100秒时,需要执行两个任务。由于只有一个线程可用,因此它执行第一个任务(第二个任务在队列中等待)。一旦第一个任务完成,线程就会从队列中选择第二个任务并完成它。
您可以在两个任务中打印出线程ID,并可以验证它们确实由同一线程处理。
编辑: 因此,基本上,以固定间隔安排的任务会以两次固定间隔执行多次。在这些时间间隔内,我们池中的单个线程处于空闲状态,并且能够选择其他任务来执行。这就是单个线程执行两个任务的方式。