繁体   English   中英

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

[英]Does thread used in @Scheduled annotation released to pool before finishing execution?

我有 5 个 @Scheduled 注释方法,我的 ThreadPoolTask​​Scheduler 的池大小是 10。我的方法的注释是相同的,就像这样。

@Scheduled(fixedDelay = 1000, initialDelay = 10000)

我的问题是;

当其中一个调度方法从池中获取线程并开始运行时; 它是否在执行完成之前将线程释放到池中? (例如在上下文切换等的情况下)还是使用该线程直到执行结束?

我的意思是有可能计划任务的某些部分是用 thread-1 完成的,而某些部分是用 thread-2 完成的吗?

线程处理很复杂,我的理解不如其他人那么好,但这里是我对@Scheduled Spring 注释如何工作的简要说明的尝试:

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#scheduling-task-scheduler

它将带注释的代码,即任务代码,提交给称为执行器的高级并发对象。 执行器类是ThreadPoolTaskExecutor 该类将任务提交到线程池,由池中的第一个可用线程运行。 您设置的线程池大小决定了您可以拥有多少个活动线程。 如果将allowCoreThreadTimeOut设置为true则池中在超时间隔内没有可用工作的线程将被终止。

Spring 使用一个ThreadPoolTaskExecutor来管理线程池:

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

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

最终, java.lang.Thread类运行由ThreadPoolTaskExecutor创建的 Runnable 或 Callable 实例。 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 根据超时间隔在线程中循环并做一些工作,然后在线程之间连续暂停和切换直到任务完成。

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

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

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

java.util.concurrent 中的大多数执行器实现都使用线程池,它由工作线程组成。 这种线程与其执行的 Runnable 和 Callable 任务分开存在,通常用于执行多个任务。

使用工作线程可以最大限度地减少线程创建造成的开销。 线程对象使用大量内存,在大型应用程序中,分配和取消分配许多线程对象会产生大量内存管理开销。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM