繁体   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