[英]cancelling current task and reuse the same thread while creating another task in java
請花時間閱讀以下內容。 非常感謝您的幫助
我有一個需要監視一些實時活動的場景。 假設某個方法在毫秒內被實時調用。 我必須監視好像第一次調用該方法以及何時最后調用該方法。
因此,在該方法被最后擊中之后,我需要等待一段時間,例如10秒鍾,然后查看在該時間內是否沒有再次調用它。 如果未調用,則需要運行一些代碼。
我想使用ExecuterService並使用newCachedThreadPool() 。 但是我對如何實現這一點感到困惑。
如果您不確定我在說什么,請舉個例子,例如,當網絡出現故障時,並且u在接收到心跳信號時突然突然停止接收它,然后在屏幕上顯示一些錯誤消息,例如Connection not available。 在我的情況下,它的某些第三方應用程序正在發送消息,並且它只是一種通信方式。 例如,我的應用程序發送了一些請求,而其他應用程序則繼續發送響應。 因此,我需要監視該響應,並且某種程度上需要知道何時收到上一個響應。
我的方法 -我想到了每次調用該方法都會執行一個任務,該方法將等待10秒,並且在10秒之內,如果再次調用該方法,它將以某種方式取消當前任務並創建另一個任務(或在可能的情況下重用) ),它將再次運行10秒鍾。 這將一直持續到收到最后一條消息為止(該方法最后一次調用時),並且在此之后10秒鍾的延遲結束后,將執行任務並運行一些代碼以在UI上顯示錯誤消息。
我以前使用過Timer,它解決了這個問題,但作為新Timer出現了性能問題,每次接收到新消息時都會實例化新的TimerTask,從而創建了許多垃圾回收器無法快速回收的對象,從而導致outOfMemorry錯誤,使服務器無響應。 顯然,這是一個錯誤的代碼,這就是為什么我在這里尋求幫助。
請幫助我提供一些解決此問題的方法。
如果您使用最基本的工具進行處理,這將非常容易-有時遇到簡單問題時,諸如線程池之類的增強工具只會分散瑣碎的解決方案。
假設您有一個簡單的線程(Runnable)。 該線程檢查時間戳以查看該時間戳是否為10秒。 如果是,則通知您的聽眾;否則,請延遲幾毫秒,然后再次檢查。
現在,您的方法所要做的就是每次運行時將(易失)時間戳更新為“現在”。 這里可能還有其他一些業務規則要實現,但這應該是一個很好的基礎。
現在唯一的問題是如何通知聽眾。 如果這種情況很少發生,您可能可以在檢查時間的同一線程上調用它們-但我認為您可以排除這種情況。 如果它發生的頻率更高,但又不想/不需要它“嵌套”您的通知,則可以使第二個線程無處閑逛,除非在由觀察者線程觸發時通知客戶端。
如果您需要“嵌套”通知(在原始通知返回之前通知偵聽器),則需要一個線程池以使通知繼續進行。
最后,我想如果您想在每10秒鍾不捕獲定時器,但又不想嵌套,則定時線程可以將“事件”推送到線程安全隊列中,而“通知”線程可以將其退出並一次發送一個事件。
那應該涵蓋所有可能性。
您可以使用ScheduledExecutorService。
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
java.util.concurrent.Executors.newCachedThreadPool
:
創建一個線程池,該線程池根據需要創建新線程,但是將在先前構造的線程可用時重用它們。 這些池通常將提高執行許多短期異步任務的程序的性能。 如果可用,執行調用將重用以前構造的線程。 如果沒有可用的現有線程,則將創建一個新線程並將其添加到池中。 六十秒內未使用的線程將終止並從緩存中刪除。 因此,保持空閑時間足夠長的池不會消耗任何資源。 請注意,可以使用ThreadPoolExecutor構造函數創建具有相似屬性但細節不同(例如,超時參數)的池
由於您有許多短期任務,因此緩存線程池是最佳選擇。
簡短示例:
public class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s){
this.command=s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
processCommand();
System.out.println(Thread.currentThread().getName()+" End.");
}
private void processCommand() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.command;
}
}
要運行WorkerThread
使用:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
Runnable worker = new WorkerThread("threadName");
executor.execute(worker);
要停止使用WorkerThread
:
executor.shutdown();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.