简体   繁体   中英

get a PriorityBlockingQueue to be in the right order in java

I have tried to make a custom ThreadPoolExecuter that holds a PriorityBlockingQueue as his queue. I have tried to make the queue to make the PriorityBlockingQueue to order his tasks from the lower priorty to the higher priority and I couldnt do it. I will be happy to get some help.

customExecuter code:

public  class CustomExecutor extends ThreadPoolExecutor implements Comparator<Task> {
    private int maxPriority = 0;
    private boolean isShutdown = false;

        public CustomExecutor() {
            super(Runtime.getRuntime().availableProcessors() / 2,
                    Runtime.getRuntime().availableProcessors() -1
                    ,300,TimeUnit.MILLISECONDS,new PriorityBlockingQueue<>());
    }
    private <T> Future<T> submitTask(Task task) {
            if (task.getPriority().getPriorityValue()>maxPriority)
                maxPriority=task.getPriority().getPriorityValue();
        if (isShutdown) {
            System.out.println("Thread pool has already been shut down. Cannot submit task");
            return null;
        }
        return super.submit(task);
    }

    public <T> Future<T> submit(Callable<T> callable,TaskType priority) {
            Task task=new Task(callable,priority);
        return submitTask(task);
    }
    //OTHER is default because it has the lowest priority(highest number)
    public <T> Future<T> submit(Callable<T> callable) {
        Task task=new Task(callable,TaskType.OTHER);
        return submitTask(task);
    }
    public int getCurrentMax() {
        return maxPriority;
    }
    public void gracefullyTerminate() {
        isShutdown = true;
        super.shutdown();
    }

    @Override
    public int compare(Task o1, Task o2) {
        return Integer.compare(o2.getPriority().getPriorityValue(), o1.getPriority().getPriorityValue());
    }

Task code:

public class Task implements Callable {
        private Callable callable;
        private  TaskType priority;
    public<T> Task(Callable<T> callable, TaskType priority) {
        this.callable = callable;
        this.priority = priority;
    }
    public TaskType getPriority() {
        return priority;
    }
    public static <T> Task createTask(Callable<T> task, TaskType priority)
    {
        Task newTask=new Task(task,priority);
        return newTask;
    }
    @Override
    public Object call() throws Exception {
        return  callable.call();
    }

enum for TaskType for the priority part:

public enum TaskType {
    COMPUTATIONAL(1){
        @Override
        public String toString(){return "Computational Task";}
    },
    IO(2){
        @Override
        public String toString(){return "IO-Bound Task";}
    },
    OTHER(3){
        @Override
        public String toString(){return "Unknown Task";}
    };
    private int typePriority;
    private TaskType(int priority){
        if (validatePriority(priority)) typePriority = priority;
        else
            throw new IllegalArgumentException("Priority is not an integer");
    }
    public void setPriority(int priority){
        if(validatePriority(priority)) this.typePriority = priority;
        else
            throw new IllegalArgumentException("Priority is not an integer");
    }
    public int getPriorityValue(){
        return typePriority;
    }
    public TaskType getType(){
        return this;
    }
    /**
     * priority is represented by an integer value, ranging from 1 to 10
     * @param priority
     * @return whether the priority is valid or not
     */
    private static boolean validatePriority(int priority){
        if (priority < 1 || priority >10) return false;
        return true;
    }

I have tried to test my code and I debugged it and which ever task that is submitted first is executed first. I noticed that the priority queue size is always 0. maybe I need to add that tasks to the queue in other way then submit?
here is my test:

 public static final Logger logger = LoggerFactory.getLogger(Tests.class);

    @Test
    public void Test1() {
        CustomExecutor customExecutor = new CustomExecutor();
        Callable<Double> callable1 = () -> {
            return 1000 * Math.pow(1.02, 5);
        };
        Callable<String> callable2 = () -> {
            StringBuilder sb = new StringBuilder("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
            System.out.println(sb);
            return sb.reverse().toString();
        };
        Future<String> reverseTask = customExecutor.submit(callable2, TaskType.IO);
        Future<Double> priceTask = customExecutor.submit(() -> {
            return 1000 * Math.pow(1.02, 5);
        }, TaskType.COMPUTATIONAL);
        Task task = Task.createTask(() -> {
            int sum = 0;
            for (int i = 1; i <= 10; i++) {
                sum += i;
            }
            System.out.println(sum);
            return sum;
        }, TaskType.COMPUTATIONAL);
        Future sumTask = customExecutor.submit(task);
        final int sum;
        try {
            sum = (int)sumTask.get(1, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            throw new RuntimeException(e);
        }
        logger.info(() -> "Sum of 1 through 10 = " + sum);

        final Double totalPrice;
        final String reversed;
        try {
            totalPrice = priceTask.get();
            reversed =  reverseTask.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
        logger.info(() -> "Reversed String = " + reversed);
        logger.info(() -> String.valueOf("Total Price = " + totalPrice));
        logger.info(() -> "Current maximum priority = " + customExecutor.getCurrentMax());
        customExecutor.gracefullyTerminate();
    }
the terminal looks like this:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
55
Jan 09, 2023 12:43:25 AM Ex2Part2.Tests Test1
INFO: Sum of 1 through 10 = 55
Jan 09, 2023 12:43:25 AM Ex2Part2.Tests Test1
INFO: Reversed String = ZYXWVUTSRQPONMLKJIHGFEDCBA
Jan 09, 2023 12:43:25 AM Ex2Part2.Tests Test1
INFO: Total Price = 1104.0808032
Jan 09, 2023 12:43:25 AM Ex2Part2.Tests Test1
INFO: Current maximum priority = 3

which is wrong because the task with priority 2 is executed first insted of the class with priority 1.

If you have an existing list of tasks that you want to submit and ensure that the highest priority task is executed before any others, you have two choices:

  1. Turn off the consumer (ie the thing that is removing tasks from the queue) before you start adding tasks, and then turn on the consumer after all the tasks are added.
  2. Put all of the tasks into a list and call the PriorityQueue constructor that takes a collection. Doing so ensures that all of the tasks are in the queue in the proper order before you even create the consumer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM