`

优先级对列PriorityBlockingQueue

 
阅读更多

优先级对列PriorityBlockingQueue

转自:http://blog.sina.com.cn/s/blog_6145ed8101010q1y.html

 

PriorityBlockingQueue里面存储的对象必须是实现Comparable接口。队列通过这个接口的compare方法确定对象的priority。

规则是:当前和其他对象比较,如果compare方法返回负数,那么在队列里面的优先级就比较搞。

下面的测试可以说明这个断言:

查看打印结果,比较take出来的Entity和left的entity,比较他们的priority

package com.java.exam1;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

public class TestPriorityQueue {  
   
    static Random r=new Random(47);  
      
    public static void main(String args[]) throws InterruptedException{  
        final PriorityBlockingQueue q=new PriorityBlockingQueue();  
        ExecutorService se=Executors.newCachedThreadPool();  
        //execute producer  
        se.execute(new Runnable(){  
            public void run() {  
                int i=0;  
                while(true){  
                    q.put(new PriorityEntity(r.nextInt(10),i++));  
                    try {  
                        TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));  
                    } catch (InterruptedException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
                }  
            }  
        }); 
          
        //execute consumer  
        se.execute(new Runnable(){  
            public void run() {  
                while(true){  
                    try {  
                        System.out.println("take-- "+q.take()+" left:-- ["+q.toString()+"]");  
                        try {  
                            TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));  
                        } catch (InterruptedException e) {  
                            // TODO Auto-generated catch block  
                            e.printStackTrace();  
                        }  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }  
        });  
        try {  
            TimeUnit.SECONDS.sleep(5);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        System.out.println("shutdown");  
    }  
 
}  
 
class PriorityEntity implements Comparable<PriorityEntity> {  
    private static int count=0;  
    private int id=count++;  
    private int priority;  
    private int index=0;  
 
    public PriorityEntity(int _priority,int _index) {  
        this.priority = _priority;  
        this.index=_index;  
    }  
      
    public String toString(){  
        return id+"# [index="+index+" priority="+priority+"]";  
    }  
 
    //数字小,优先级高  
    public int compareTo(PriorityEntity o) {  
        return this.priority > o.priority ? 1 
                : this.priority < o.priority ? -1 : 0;  
    }  
 
    //数字大,优先级高  
//  public int compareTo(PriorityTask o) {  
//      return this.priority < o.priority ? 1  
//              : this.priority > o.priority ? -1 : 0;  
//  }  

 

问题:有没有人在使用时,发现将添加在PriorityBlockingQueue的一系列元素打印出来,队列的元素其实并不是全部按优先级排序的,但是队列头的优先级肯定是最高的?

回复:PriorityBlockingQueue队列添加新元素时候不是将全部元素进行顺序排列, 而是从某个指定位置开始将新元素与之比较,一直比到队列头,这样既能保证队列头一定是优先级最高的元素,又能减少排序带来的性能消耗(个人判断,仅供参 考),可以查看PriorityBlockingQueue源码,添加元素有调用一个方法是 PriorityQueue.siftUpUsingComparator(或siftUpComparable),这个方法里有个排序算法:

private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (key.compareTo((E) e) >= 0)
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = key;
    }

不是全部排序。

但是这样会出现一个情况,取完队列头时候,后面的剩余的元素不是排序的,岂不是不符合要求了,继续查看源码,发现每取一个头元素时候,都会对剩余的元素做一次调整,这样就能保证每次队列头的元素都是优先级最高的元素,查看取元素时候调用的一个方法PriorityQueue.:

 private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }

 private void siftDownUsingComparator(int k, E x) {
        int half = size >>> 1;
        while (k < half) {
            int child = (k << 1) + 1;
            Object c = queue[child];
            int right = child + 1;
            if (right < size &&
                comparator.compare((E) c, (E) queue[right]) > 0)
                c = queue[child = right];
            if (comparator.compare(x, (E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        }
        queue[k] = x;
    }

分享到:
评论

相关推荐

    IP优先级、TOS优先级、DSCP优先级和802.1p优先级的区别

    IP优先级和TOS优先级在IP层定义,而DSCP是对TOS字段的扩展,提供了更细粒度的分类。802.1p优先级则是在数据链路层进行优先级标记,适用于局域网环境。这些优先级机制的合理运用,有助于在网络中实现高效的流量管理和...

    不考虑优先级对算术表达式求值

    表达式计算是实现程序设计语言的基本问题之一,也...设计一个程序,不考虑优先级对算术表达式求值的过程 【基本要求】 以字符序列的形式从终端输入语法正确的,不含变量的整数表达式。实现对算术四则运算表达式的求值。

    Verilog HDL 运算符 优先级

    Verilog HDL 运算符优先级是指在 Verilog HDL 中各种运算符的执行顺序和优先级,了解运算符优先级对编写高效的 Verilog 代码非常重要。 Verilog HDL 运算符优先级可以分为以下几类: 一、位选择和部分选择运算符 ...

    基于频率优先级的切换应用、优先级切换流程、参数配置.docx

    3. **基于频率优先级的切换测量标志位配置**:这一步涉及控制是否允许对相邻频点进行基于频率优先级的切换测量。如果设置为ENABLE,该频点就可以参与测量和切换;反之,如果设置为DISABLE,则不会进行基于频率优先级...

    C++进程优先级调度进程优先级调度进程优先级调度

    在Priority函数中,我们按照优先级对进程进行排序,并将其加入执行队列。在Output函数中,我们使用了printf函数来输出队列信息。 在整个程序中,我们使用了链表来实现队列的操作,使用了结构体来存储进程的信息。...

    RTOS优先级反转问题分析

    优先级继承法是指将低优先级任务的优先级继承给高优先级任务,以避免高优先级任务被低优先级任务阻塞。 此外,文章还提出了改进方法:优先级交换法。优先级交换法是指在高优先级任务和低优先级任务之间交换优先级,...

    线程池提交优先级,执行优先级

    线程池提交优先级,执行优先级

    中断优先级的理解_中断优先级_源码

    中断优先级是嵌入式系统,特别是微控制器如STM32F103中的关键概念。在嵌入式系统设计中,中断处理是实时性、响应速度和系统效率的重要因素。中断优先级的理解对于开发高效、可靠的软件至关重要。 中断是处理器响应...

    设置线程的优先级

    线程的优先级是操作系统调度线程执行时的一个重要概念,它决定了系统如何分配处理器时间。在多任务环境中,线程优先级可以帮助决定哪个线程应该先被执行,从而影响程序的响应速度和整体性能。本篇文章将深入探讨线程...

    VC++ 线程优先级 示例程序

    在编程领域,线程是操作系统分配CPU执行时间的基本单元,多线程技术使得程序能够同时执行多个任务。...通过“赛马”示例程序,开发者能直观理解线程优先级对程序执行顺序的影响,从而更好地设计和优化多线程应用。

    操作系统——动态优先级调度算法源代码.rar_优先级_优先级调度_优先级调度算法_动态优先级_动态优先级 算法

    操作系统——动态优先级调度算法源代码,多道系统中多进程并发执行,为了提高系统性能解决进程死锁问题,进程的优先级是动态变化的。正在执行的进程优先级会随时间降低,而挂起的进程或等待的进程的优先级会逐渐升高...

    最高优先级编码器;最高优先级编码器

    最高优先级编码器是一种数字逻辑电路,用于将多个输入信号转换为一个或多个输出信号,其中最高优先级的输入信号被编码为输出。在给定的代码中,它是一个使用VHDL(VHSIC硬件描述语言)编写的实体,名为`priority`,...

    单片机中断优先级,含C语言及汇编程序

    - 中断是单片机对外部事件的一种快速响应机制。当外部或内部事件发生时,单片机会暂停当前任务,转而去执行中断服务程序,处理该事件。 - 中断源可以包括定时器中断、串口通信中断、外部硬件中断等。 2. **中断...

    模拟进程优先级调度算法

    模拟进程优先级调度算法可以帮助我们更好地理解进程调度的工作原理及其对系统性能的影响。通过实际的编程模拟,我们可以观察到不同参数设置下系统的行为变化,从而优化调度策略,提高系统的整体效率。

    基于 kotlin Channel 的优先级异步任务队列

    TaskPriority 优先级的标准如下: TaskPriority.LOW 当优先级相同 按照插入次序排队 默认优先级是 TaskPriority.DEFAULT 任务 任务种类可分为 2 种,分别是 执行时间不确定 的任务和 执行时间确定 的任务。执行...

    从语言优先级及优先级口诀

    以下是对标题和描述中提到的“优先级口诀”的详细解释: 1. **括号运算符** ((), [], ., -&gt;): 这是最高的优先级,括号可以用来改变表达式的计算顺序。[]. 对象成员访问,-&gt; 指针成员访问。 2. **一元运算符** (!, ...

    UCOSII优先级反转及解决

    优先级继承关注于当高优先级任务等待资源时临时提升低优先级任务的优先级,而优先级天花板则是在资源被访问时就将访问任务的优先级提升到一个预定的最高优先级。两者的主要区别在于,优先级继承更加动态,依赖于任务...

    双优先编码器 该器件返回最高优先级和次最高优先级请求代码

    双优先编码器 该器件返回最高优先级和次最高优先级请求代码 ...1、列出真值表 2、设计电路、编写代码 3、设计测试电路代码 4、综合 5、用测试代码测试 6、设计实验电路(描述如何在实验室完成电路的硬件测试和验证)

    优先级反转的嵌入式资料

    优先级反转是嵌入式系统中一种常见的多任务调度问题,尤其在实时操作系统(RTOS)中,它可能对系统的响应时间和整体性能造成显著影响。在本文中,我们将深入探讨优先级反转现象,以及如何通过信号量来管理和解决这个...

Global site tag (gtag.js) - Google Analytics