使用@Scheduling按@调度(fixedRate= 10000)运行方法,并通过实现SchedulingConfigurer设置@调度线程
@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(10);
}如果我使用Thread.sleep或Lock,除非Thread.sleep唤醒或锁被清除,否则执行器不会创建其他线程。
有人能解释内部工作,如果我有10个池大小,他们10个线程应该以10000毫秒的速度创建。
发布于 2017-12-20 12:59:21
基本上,这样的行为来自于ScheduledExecutorService实现,spring在内部使用。如果要运行此代码,您将注意到相同的行为:
public static void main(String[] args) throws Exception {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
executor.schedule(() -> {
System.out.println("Running task in thread " + Thread.currentThread().getId());
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
System.out.println("interrupted while sleeping");
}
}, 1000, TimeUnit.MILLISECONDS);
Thread.sleep(10000);
executor.shutdownNow();
}当您将任务提交到计划线程池时,它将使用RunnableScheduledFuture包装,然后传递给delayedExecute方法。此方法将任务添加到任务队列中,如果当前工作人员的数量少于corePoolSize,则启动新的工作人员。工作者试图从队列中获取一个任务,并处理它调用run方法。有一个专用的DelayedWorkQueue实现,它只在任务准备好执行时才返回任务。下面是run方法RunnableScheduledFuture的样子:
/**
* Overrides FutureTask version so as to reset/requeue if periodic.
*/
public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))
cancel(false);
else if (!periodic)
ScheduledFutureTask.super.run();
else if (ScheduledFutureTask.super.runAndReset()) {
setNextRunTime();
reExecutePeriodic(outerTask);
}
}如您所见,它调用runAndReset中的实际任务逻辑,计算下一个运行时间,并再次向队列提交相同的更新任务(reExecutePeriodic几乎与schedule相同)。对于所有的执行,只有一个定期任务,在上次执行完成后,会一次又一次地重新提交,并进行更新。因此,这样的线程池在任何给定时刻只运行每种任务类型的单个实例,并且只针对不同类型的任务进行缩放。
如果您对spring调度任务的方式感兴趣,请查看ScheduledTaskRegistrar类,特别是scheduleFixedDelayTask方法。
发布于 2017-12-19 16:52:04
在使用线程池的情况下:默认情况下,池中将有10个线程(已经初始化)。第一次执行@调度时,该函数将在池中的线程中执行(现在剩下9个线程),如果函数尚未完成并再次执行@调度,则您的函数将在池中的其他线程中执行,因此您的池中保留了8个线程。(8个空闲线程,2个正在运行的线程)
如果不使用线程池,则只使用一个线程。
春季文件:
如果不提供“池大小”属性,默认线程池将只有一个线程。调度程序没有其他配置选项。
https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/scheduling.html
https://stackoverflow.com/questions/47891397
复制相似问题