簡體   English   中英

在Java中創建另一個任務時取消當前任務並重用同一線程

[英]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秒鍾不捕獲定時器,但又不想嵌套,則定時線程可以將“事件”推送到線程安全隊列中,而“通知”線程可以將其退出並一次發送一個事件。

那應該涵蓋所有可能性。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM