簡體   English   中英

如何在ArrayBlockingQueue中使用Predicate方法“removeIf”

[英]How to use the method “removeIf” using a Predicate in a ArrayBlockingQueue

我有以下課程:

WorkerTask.java

   public interface WorkerTask extends Task {

   // Constants
   public static final short WORKERTASK_SPIDER = 1;
   public static final short WORKERTASK_PARSER = 2;
   public static final short WORKERTASK_PRODUCT = 3;

   public int getType();
}

WorkerPool.java

class workerPool {

     private ThreadPoolExecutor executorPool_;

     //----------------------------------------------------  

     public WorkerPool(int poolSize) 
     {
        executorPool_ = new ThreadPoolExecutor(
           poolSize,5,10,TimeUnit.SECONDS,
           new ArrayBlockingQueue<Runnable>(10000000,false),
           Executors.defaultThreadFactory()
     );

     //----------------------------------------------------        

     public void assign(WorkerTask workerTask) {
         executorPool_.execute(new WorkerThread(workerTask));
     }

     //----------------------------------------------------  

     public void removeTasks(int siteID) {
        executorPool_.getQueue().removeIf(...);     
     }
}

我想調用方法removeTasks來刪除一定數量的掛起任務,但我不知道如何使用方法removeIf。 它說:刪除此集合中滿足給定謂詞的所有元素,但我不知道如何創建參數Predicate。 任何的想法?

如果你有一個Queue<WorkerTask> ,你可以這樣做:

queue.removeIf(task -> task.getSiteID() == siteID)

有幾個問題。 一個問題是你從getQueue()獲得的隊列是BlockingQueue<Runnable>而不是Queue<WorkerTask> 如果要將Runnable實例提交到池中,則隊列可能包含對實際任務的引用; 如果是這樣,你可以將它們WorkerTaskWorkerTask 但是,這不能保證。 此外, ThreadPoolExecutor的類doc說(在“隊列維護”下):

方法getQueue()允許訪問工作隊列以進行監視和調試。 強烈建議不要將此方法用於任何其他目的。 當大量排隊的任務被取消時,兩個提供的方法remove(Runnable)purge()可用於協助存儲回收。

查看remove(Runnable)方法,其文檔說

在放入內部隊列之前,它可能無法刪除已轉換為其他表單的任務。

這表明您應該掛起已提交的Runnable實例,以便稍后調用remove() 或者,調用submit(Runnable)獲取Future並保存這些實例以取消它們。

但是還有第二個問題可能導致這種方法不足。 假設您已找到一種方法從隊列中刪除或取消匹配的任務。 另一個線程可能已決定提交匹配的新任務,但尚未提交。 這里有競爭條件。 您可以取消已排隊的任務,但在完成之后,您無法保證尚未提交新的匹配任務。

這是另一種方法。 據推測,當你取消(或者不管)某個站點ID時,有一些邏輯可以停止提交與該ID相匹配的新任務。 問題是如何處理“在飛行中”的匹配任務,即隊列中或即將入隊的任務。

不要嘗試取消匹配的任務,而是更改任務,以便在其網站ID被取消后,任務變為無操作。 您可以在ConcurrentHashMap記錄網站ID的取消。 任何任務都會在開始工作之前檢查此地圖,如果網站ID存在,則只返回。 向站點添加站點ID將立即生效,確保不會開始該站點ID上的新任務。 (已經啟動的任務將運行完成。)任何正在進行的任務最終將從隊列中排出,而不會導致任何實際工作發生。

謂詞是一個接收輸入並返回布爾值的函數。

如果您使用的是java 8,則可以使用lambda表達式: (elem) -> return elem.id == siteID

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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