在實作一個函式在特定時間范圍內處理任務時(例如,每隔 1 分鐘監控一個值,總共 10 分鐘時間限制),流行的解決方案是使用Timer或ScheduledExecutorServicejava util 類在單獨的執行緒上調度任務.
想知道為什么不在當前執行緒上實作定時任務而不是創建一個新執行緒來處理它?
uj5u.com熱心網友回復:
多執行緒的全部意義在于從運行應用程式的初始執行緒中卸載作業。
休眠到特定時間的執行緒不做任何其他作業。如果您的應用程式的主執行緒是睡著的,那么您的應用程式將完全掛起且無用。如果運行你的 GUI 的執行緒是睡著的,那么你的應用程式對用戶來說似乎是凍結的,顯然是崩潰的,并且實際上是無用的。
此外,正如所評論的,當前用 Java 實作的執行緒在記憶體和 CPU 方面相對昂貴。所以我們通常避免一次運行超過幾個/幾個/幾十個執行緒。未來,如果Project Loom的虛擬執行緒成功,這種情況可能會徹底改變。
你評論說:
我想也許我可以開始時間停止->監視器->回傳->睡眠當前執行緒->監視器,當條件滿足或超時時退出監視器?
這實際上就是ScheduledExecutorService所做的。您將任務定義為Runnable或Callable。執行器服務會定期運行您的任務。在該任務中,您可以檢查您正在等待的條件。
因此,您無需重新發明輪子。使用Java 內置的Executors框架;太好了。
搜索該類名稱。關于這個主題已經寫了很多,其中一些是我撰寫的。搜索以了解更多資訊。
關于Timer,該類在幾年前被 Executors 框架取代。Javadoc 中記錄了這一事實。
您澄清說您的目標是每分鐘檢查一個條件最多十次。
一種方法是讓任務自行重新安排。
public class ConditionCheckingTask implements Runnable
{
private final ScheduledExecutorService ses ;
private final Instant whenInstantiated = Instant.now() ;
// Constructor
public ConditionCheckingTask( final ScheduledExecutorService ses ) {
this.ses = ses ;
}
@Override
public void run() {
if( someConditionIsTrue ) {
doSomething ;
} else if ( ChronoUnit.MINUTES.between( this.whenInstantiated , Instant.now() ) > 10 ) {
// We have exceeded our time limit, so let this task die.
return ;
} else { // Else wait a minute to check condition again.
this.ses.schedule( this , 1 , TimeUnit.MINUTES ) ;
}
}
}
確保訪問someConditionIsTrue是執行緒安全的。例如,如果某個其他執行緒正在翻轉一個布爾標志以向我們的任務發出信號,則將該標志設為AtomicBoolean. 要了解更多資訊,請搜索 Stack Overflow,并閱讀下面列出的書籍。
在您的應用程式的某處,實體化并記住一個ScheduledExecutorService物件。
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
請務必在您的應用退出之前最終關閉執行程式服務。搜索以了解更多資訊。這已在 Stack Overflow 上多次解決。
實體化您的任務。將調度的執行器服務傳遞給任務的建構式,以便它可能每分鐘重新調度一次。
ConditionCheckingTask task = new ConditionCheckingTask( scheduledExecutorService ) ;
要開始作業,請安排運行該任務的時間很少或沒有延遲。
scheduledExecutorService.schedule( task , 0 , TimeUnit.MINUTES ) ;
作為第一次運行的一部分,任務將自行重新安排。
注意:在部署任何多執行緒代碼之前,一定要好好學習 Goetz 等人的優秀書籍,Java Concurrency In Practice。
uj5u.com熱心網友回復:
想知道為什么不在當前執行緒上實作定時任務而不是創建一個新執行緒來處理它?
您的“當前”執行緒可能是處理主請求的執行緒(例如,http 請求或任務/作業協調器)。其中一個的定時任務會將該執行緒系結到任何其他作業,直到任務完成。在基于 http 的服務上,這可能導致 http 超時等,這在最終用戶體驗和計算資源使用方面都不是一個好的設計。通常作為一種好的做法,您不會為該任務生成另一個新執行緒,而是使用執行緒池來有效利用資源。
uj5u.com熱心網友回復:
您不能在當前執行緒中執行此操作,因為您的主程式在它自己的執行緒中運行,并且您對它沒有太多控制權。你最多可以讓它進入睡眠狀態。因此,您將在一個執行緒上啟動主程式,該執行緒將分拆另一個執行緒以按計劃運行您的任務。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/433425.html
