简体   繁体   English

让 PriorityBlockingQueue 在 java 中以正确的顺序排列

[英]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.我试图制作一个自定义的 ThreadPoolExecuter,它将 PriorityBlockingQueue 作为他的队列。 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.我试图让队列使 PriorityBlockingQueue 将他的任务从低优先级排序到高优先级,但我做不到。 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:优先级部分的 TaskType 枚举:

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?我注意到优先级队列大小始终为 0。也许我需要以其他方式将该任务添加到队列中然后提交?
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.这是错误的,因为优先级为 2 的任务首先执行优先级为 1 的 class。

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.将所有任务放入一个列表中,并调用接受一个集合的PriorityQueue 构造函数 Doing so ensures that all of the tasks are in the queue in the proper order before you even create the consumer.这样做可以确保在创建消费者之前所有任务都以正确的顺序排列在队列中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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