首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有优先级任务的线程池执行器,并避免饥饿

具有优先级任务的线程池执行器,并避免饥饿
EN

Stack Overflow用户
提问于 2016-08-15 18:23:28
回答 1查看 2.9K关注 0票数 1

对于我的用例,我需要一个可以根据优先级执行任务的executor。实现这一点的简单方法是使用具有PriorityBlockingQueue的线程池并覆盖newTaskFor(),以返回基于任务优先级可比较的自定义未来任务。

代码语言:javascript
复制
//Define priorities
public enum Priority {
    HIGH, MEDIUM, LOW, VERYLOW;
}

优先任务

代码语言:javascript
复制
//A Callable tasks that has priority. Concrete implementation will implement 
//call() to do actual work and getPriority() to return priority
public abstract class PriorityTask<V> implements Callable<V> {
    public abstract Priority getPriority ();
}

实际的执行器实现

代码语言:javascript
复制
public class PriorityTaskThreadPoolExecutor <V> {
    int _poolSize;
    private PriorityBlockingQueue<Runnable> _poolQueue = 
                                       new PriorityBlockingQueue<Runnable>(500); 
    private ThreadPoolExecutor _pool;

    public PriorityTaskThreadPoolExecutor (int poolSize) {
        _poolSize = poolSize;

        _pool = new ThreadPoolExecutor(_poolSize, _poolSize, 5, TimeUnit.MINUTES, 
                                      _poolQueue) {
                        //Override newTaskFor() to return wrap PriorityTask 
                        //with a PriorityFutureTaskWrapper.
                        @Override
                        protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
                            return new PriorityFutureTaskWrapper<V>((PriorityTask<V>) c);
                        }
                };

        _pool.allowCoreThreadTimeOut(true);
    }

    public Future<V> submit (PriorityTask<V> task) {
        return _pool.submit(task);
    }

}

//A future task that wraps around the priority task to be used in the queue
class PriorityFutureTaskWrapper<V> extends FutureTask<V> 
                             implements Comparable <PriorityFutureTaskWrapper<V>> {
    PriorityTask<V> _priorityTask;

    public PriorityFutureTaskWrapper (PriorityTask<V> priorityTask) {
        super(priorityTask);
        _priorityTask = priorityTask;
    }

    public PriorityTask<V> getPriorityTask () {
        return _priorityTask;
    }

    @Override
    public int compareTo(PriorityFutureTaskWrapper<V> o) {
        return _priorityTask.getPriority().ordinal() - 
               o.getPriorityTask().getPriority().ordinal();
    }
}

这样做的问题是,在我的用例中,低优先级任务有可能永远处于饥饿状态。我想避免这种情况。我找不到一种干净的方法来使用java中可用的执行器/池来做到这一点。因此,我正在考虑编写自己的executor。我有两种不同的方法。

1)带PriorityBlockingQueue的自定义线程池。将有一个单独的线程,用于检查队列中的任务期限。较旧的任务将被删除,并以提升的优先级重新添加。

2)我的用例将只有有限数量的优先级,比如1-4。对于每个优先级,我将有4个不同的队列。现在,当定制池中的线程必须处理下一个任务时,它将按以下顺序扫描队列,而不是阻塞队列。

40%的线程- Q1、Q2、Q3、Q4

30%的线程- Q2、Q1、Q3、Q4

20%的线程- Q3、Q1、Q2、Q4

10%的线程- Q4、Q1、Q2、Q3

当线程被通知队列中有新的添加时,或者当该线程执行的当前任务完成时,它将完成扫描。其他时候,线程将会等待。但是,与队列上的阻塞相比,扫描的效率会稍低一些。

Apprach 2更适合我的用例。

有没有人尝试过这些方法中的任何一种,或者针对类似的用例尝试过不同的方法?有什么想法/建议吗?

EN

回答 1

Stack Overflow用户

发布于 2016-08-16 08:21:03

here已经讨论过,没有简单的方法来更改PriorityQueue中已插入元素的优先级

第二种选择应该易于实现,比如处理高优先级队列中的任务比处理低优先级队列中的任务多

您还可以考虑为每个优先级设置不同的ThreadPools,每个池中的线程数量取决于任务的优先级。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38953331

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档