簡體   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