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

标签 java spring scheduled-tasks java-threads spring-scheduled

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

@Scheduled(fixedDelay = 1000, initialDelay = 10000)

我的问题是;

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

我的意思是是否有可能计划任务的某些部分由线程 1 完成,而某些部分由线程 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

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

Spring使用ThreadPoolTask​​Executor来管理线程池:

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

保持线程池处于 Activity 状态可以减少通常在等待创建线程时增加的时间。看这个question了解更多信息。

最终,java.lang.Thread 类运行由 ThreadPoolTask​​Executor 创建的 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

线程之间的实际切换,即上下文切换is OS-dependent但一般来说,线程会在 CPU 之间划分,然后每个 CPU 根据超时间隔循环执行线程并执行一些工作,然后暂停并在线程之间不断切换,直到任务完成。

does it release the thread to pool before its execution is finished? (for example in case of context switch etc.) or this thread is used until the end of the execution?

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

以下是 Oracle documentation 的更多信息这解释了线程池:

Most of the executor implementations in java.util.concurrent use thread pools, which consist of worker threads. This kind of thread exists separately from the Runnable and Callable tasks it executes and is often used to execute multiple tasks.

Using worker threads minimizes the overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and deallocating many thread objects creates a significant memory management overhead.

One common type of thread pool is the fixed thread pool. This type of pool always has a specified number of threads running; if a thread is somehow terminated while it is still in use, it is automatically replaced with a new thread. Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever there are more active tasks than threads.

An important advantage of the fixed thread pool is that applications using it degrade gracefully. To understand this, consider a web server application where each HTTP request is handled by a separate thread. If the application simply creates a new thread for every new HTTP request, and the system receives more requests than it can handle immediately, the application will suddenly stop responding to all requests when the overhead of all those threads exceed the capacity of the system. With a limit on the number of the threads that can be created, the application will not be servicing HTTP requests as quickly as they come in, but it will be servicing them as quickly as the system can sustain.

关于java - @Scheduled 注解中使用的线程在完成执行之前是否释放到池中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55380915/

相关文章:

java - Spring Controller 下载文件不受文件系统限制

java - Spring WebFlux,如何调试我的 WebClient POST 交换?

java - 尝试将 AWS X-Ray 与 java spring @Scheduled 一起使用时收到 SubsegmentNotFoundException

java - 仅以编程方式更改 TextView 中某些文本的背景颜色

java - 自定义 Spring Data REST 生成的默认查询

java - Java 中是否有 SQLite 的驱动程序?

c# - 如何在 Microsoft Bot Framework + C# 中安排任务?

java - 如何为任务计划程序执行控制台 Java 应用程序?

java - 作为后台进程运行 java 应用程序

java - 使用 Java 从 Tomcat 容器访问系统属性