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

时间:2016-08-15 10:23:28

标签: java multithreading threadpool

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

//Define priorities
public enum Priority {
    HIGH, MEDIUM, LOW, VERYLOW;
}

优先任务

//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 ();
}

实际执行者实施

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中可用的执行程序/池执行此操作的简洁方法。所以我想写自己的执行者。我有两种不同的方法。

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更适合我的用例。

是否有人尝试过这些方法或类似用例的不同方法?有什么想法/建议?

0 个答案:

没有答案