当前位置: 首页 > 知识库问答 >
问题:

在@scheduled注释中使用的线程是否在完成执行之前释放到池中?

鱼锦
2023-03-14

我有5@scheduled带注释的方法,我的ThreadPoolTaskScheduler的池大小是10。我的方法的注释是相同的,并且是这样的。

@schedule(fixedDelay=1000,initialDelay=10000)

我的问题是;

共有1个答案

郎刚捷
2023-03-14

线程处理很复杂,我的理解不如其他人,但下面是我对@scheduleSpring注释工作原理的简要解释:

Spring使用TaskScheduler:

public interface TaskScheduler {

    ScheduledFuture schedule(Runnable task, Trigger trigger);

    ScheduledFuture schedule(Runnable task, Date startTime);

    ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);

    ScheduledFuture scheduleAtFixedRate(Runnable task, long period);

    ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);

    ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);

}

https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html#调度-task-scheduler

Spring使用ThreadPoolTaskExecutor来管理线程池:

https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/scheduling/concurrent/threadpooltaskexecutor.java

使线程池保持活动状态可以减少在等待创建线程时通常增加的时间。有关更多信息,请参阅此问题。

最终,java.lang.Thread类运行由ThreadPoolTaskExecutor创建的可运行或可调用实例。thread类实现了run()方法,该方法基本上是您希望线程运行的代码:

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc) {
...

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/lang/thread.java

线程之间的实际切换(即上下文切换)依赖于操作系统,但通常情况下,线程将被划分在CPU之间,然后每个CPU根据超时间隔循环通过线程,并执行一些工作,然后暂停并在线程之间连续切换,直到任务完成。

它是否在执行完成之前将线程释放到池中?(例如,在上下文切换等情况下)还是该线程一直使用到执行结束?

可运行的代码肯定会在操作过程中停止执行,但线程池中的线程通常会保持活动状态,直到没有更多的工作要做。

以下是Oracle文档中解释线程池的更多信息:

使用工作线程将由于线程创建而导致的开销最小化。线程对象使用了大量的内存,并且在一个大规模的应用程序中,分配和释放许多线程对象会产生很大的内存管理开销。

一种常见的线程池类型是固定线程池。这种类型的池总是有指定数量的线程在运行;如果一个线程在仍在使用时以某种方式终止,它将自动替换为一个新线程。任务通过内部队列提交到池中,每当活动任务多于线程时,该队列就会保存额外的任务。

固定线程池的一个重要优点是使用它的应用程序可以优雅地降级。要理解这一点,请考虑一个web服务器应用程序,其中每个HTTP请求都由一个单独的线程处理。如果应用程序只是简单地为每一个新的HTTP请求创建一个新线程,而系统收到的请求比它能立即处理的多,那么当所有那些线程的开销超过系统的容量时,应用程序就会突然停止对所有请求的响应。由于可以创建的线程数量受到限制,应用程序将不会像它们进入时那样快速地为HTTP请求提供服务,但它将以系统所能维持的速度为它们提供服务。

 类似资料:
  • 问题内容: 我有几种用注释的方法。 在应用程序上下文中,我具有以下注释驱动的设置: 问题是,有时某些方法的执行会延迟几秒钟甚至几分钟。 我假设即使某个方法需要一段时间才能完成执行,其他方法仍会执行。所以我不明白延迟。 有没有办法减少甚至消除延迟? 问题答案: 为了完整起见,以下代码显示了使用java config配置调度程序的最简单方法: 当需要更多控制时,可以实现一个类。

  • 问题内容: 假设我正在定义一个缓存bean,它将在启动应用程序时初始化,并以固定的间隔刷新,如下所示: 即使我未设置初始延迟,也可以确保@PostConstruct下的initializeCache()方法在第一次调度的refreshCache()调用之前立即执行吗? 问题答案: 是的,带有注解的方法可以保证首先执行。 的注释由活化ScheduledAnnotationBeanPostProces

  • 我在很多地方读过,线程池减少了线程创建开销,从而提高了性能。但是一旦线程执行完它的run方法,它就会进入dead/terminated状态,这意味着它可以再次重新启动。 那么,线程池如何处理线程的释放呢?它是否真的以某种方式保存线程以服务下一个任务,或者在每次提交任务时在内部创建新线程?

  • 我是新来的春靴AOP。 用@Before注释的AOP方法是否在java验证注释(例如@NotNull)之前运行? 我还需要为每个请求运行一些其他自定义验证,但我需要在java验证注释运行之后运行这些验证。 哪个先跑? 我的控制器: 我的建议是: