How do I implement task prioritization using an ExecutorService in Java 5?

前端 未结 6 1917
粉色の甜心
粉色の甜心 2020-11-27 03:51

I am implementing a thread pooling mechanism in which I\'d like to execute tasks of varying priorities. I\'d like to have a nice mechanism whereby I can submit a high prior

6条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-27 04:10

    I have solved this problem in a reasonable fashion, and I'll describe it below for future reference to myself and anyone else who runs into this problem with the Java Concurrent libraries.

    Using a PriorityBlockingQueue as the means for holding onto tasks for later execution is indeed a movement in the correct direction. The problem is that the PriorityBlockingQueue must be generically instantiated to contain Runnable instances, and it is impossible to call compareTo (or similiar) on a Runnable interface.

    Onto solving the problem. When creating the Executor, it must be given a PriorityBlockingQueue. The queue should further be given a custom Comparator to do proper in place sorting:

    new PriorityBlockingQueue(size, new CustomTaskComparator());
    

    Now, a peek at CustomTaskComparator:

    public class CustomTaskComparator implements Comparator {
    
        @Override
        public int compare(MyType first, MyType second) {
             return comparison;
        }
    
    }
    

    Everything looking pretty straight forward up to this point. It gets a bit sticky here. Our next problem is to deal with the creation of FutureTasks from the Executor. In the Executor, we must override newTaskFor as so:

    @Override
    protected  RunnableFuture newTaskFor(Callable c) {
        //Override the default FutureTask creation and retrofit it with
        //a custom task. This is done so that prioritization can be accomplished.
        return new CustomFutureTask(c);
    }
    

    Where c is the Callable task that we're trying to execute. Now, let's have a peek at CustomFutureTask:

    public class CustomFutureTask extends FutureTask {
    
        private CustomTask task;
    
        public CustomFutureTask(Callable callable) {
            super(callable);
            this.task = (CustomTask) callable;
        }
    
        public CustomTask getTask() {
            return task;
        }
    
    }
    

    Notice the getTask method. We're gonna use that later to grab the original task out of this CustomFutureTask that we've created.

    And finally, let's modify the original task that we were trying to execute:

    public class CustomTask implements Callable, Comparable {
    
        private final MyType myType;
    
        public CustomTask(MyType myType) {
            this.myType = myType;
        }
    
        @Override
        public MyType call() {
            //Do some things, return something for FutureTask implementation of `call`.
            return myType;
        }
    
        @Override
        public int compareTo(MyType task2) {
            return new CustomTaskComparator().compare(this.myType, task2.myType);
        }
    
    }
    

    You can see that we implement Comparable in the task to delegate to the actual Comparator for MyType.

    And there you have it, customized prioritization for an Executor using the Java libraries! It takes some bit of bending, but it's the cleanest that I've been able to come up with. I hope this is helpful to someone!

提交回复
热议问题