多线程--优先队列PriorityBlockingQueue

本文深入讲解了PriorityBlockingQueue,一种支持优先级的无界阻塞队列,探讨了其内部实现,包括数组实现、锁机制、自动扩容特性,以及如何通过自定义比较器或实现Comparable接口来指定元素排序规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

PriorityBlockingQueue是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序升序排列。也可以自定义类实现compareTo()方法来指定元素排序规则,或者初始化PriorityBlockingQueue时,指定构造参数Comparator来对元素进行排序。但需要注意的是不能保证同优先级元素的顺序。

和ArrayBlockingQueue一样内部使用数组实现,插入和获取数据使用同一把锁。不同的是,不管有无指定长度,都会实现可以实现自动扩容;在构造函数需传入comparator,用于插入元素时继续排序,若没有传入comparator,则插入的元素必须实现Comparatable接口。

构造方法

 public PriorityBlockingQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }

public PriorityBlockingQueue(int initialCapacity) {
        this(initialCapacity, null);
    }

public PriorityBlockingQueue(int initialCapacity,
                                 Comparator<? super E> comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }

public PriorityBlockingQueue(Collection<? extends E> c) {
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        boolean heapify = true; // true if not known to be in heap order
        boolean screen = true;  // true if must screen for nulls
        if (c instanceof SortedSet<?>) {
            SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
            this.comparator = (Comparator<? super E>) ss.comparator();
            heapify = false;
        }
        else if (c instanceof PriorityBlockingQueue<?>) {
            PriorityBlockingQueue<? extends E> pq =
                (PriorityBlockingQueue<? extends E>) c;
            this.comparator = (Comparator<? super E>) pq.comparator();
            screen = false;
            if (pq.getClass() == PriorityBlockingQueue.class) // exact match
                heapify = false;
        }
        Object[] a = c.toArray();
        int n = a.length;
        // If c.toArray incorrectly doesn't return Object[], copy it.
        if (a.getClass() != Object[].class)
            a = Arrays.copyOf(a, n, Object[].class);
        if (screen && (n == 1 || this.comparator != null)) {
            for (int i = 0; i < n; ++i)
                if (a[i] == null)
                    throw new NullPointerException();
        }
        this.queue = a;
        this.size = n;
        if (heapify)
            heapify();
    }

定义实体类

public class Human {
    private int maney;
    private String name;
    public Human(int maney, String name){
        this.maney = maney;
        this.name = name;
    }

    public int getManey() {
        return maney;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return getName() + "[存款:"+getManey()+"]";
    }
}

重写比较器 

public class HumanComparator implements Comparator<Human>  {
    @Override
    public int compare(Human o1, Human o2) {
        return o2.getManey() - o1.getManey();
    }
}

生产线程 

public class ProducerRunnable implements Runnable{
    private static final String name = "明刚红李刘吕赵黄王孙朱曾游丽吴昊周郑秦丘";
    private Random random = new Random();
    private PriorityBlockingQueue<Human> queue;
    public ProducerRunnable(PriorityBlockingQueue<Human> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        for(int i = 0; i < 20; i ++){
            Human human = new Human(random.nextInt(10000), "小" + name.charAt(i));
            queue.put(human);
            System.out.println(human + " 开始排队...");
        }
    }

}

消费线程 

public class ConsumerRunnable implements Runnable{

    private PriorityBlockingQueue<Human> queue;
    public ConsumerRunnable(PriorityBlockingQueue<Human> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true){
            Human take = queue.poll();
            if (take == null){
                break;
            }
            System.out.println(take + " 办理业务.");
        }
    }
}

测试类 

public class TestMain {

    public static void main(String[] args) throws InterruptedException {

        PriorityBlockingQueue<Human> queue = new PriorityBlockingQueue<>(200, new HumanComparator());
        Thread thread = new Thread(new ProducerRunnable(queue));
        thread.start();
        thread.join();
        new Thread(new ConsumerRunnable(queue)).start();
    }
}

测试结果: 

小明[存款:9296] 开始排队...
小刚[存款:765] 开始排队...
小红[存款:333] 开始排队...
小李[存款:3912] 开始排队...
小刘[存款:5732] 开始排队...
小吕[存款:3714] 开始排队...
小赵[存款:8439] 开始排队...
小黄[存款:7330] 开始排队...
小王[存款:9535] 开始排队...
小孙[存款:1421] 开始排队...
小朱[存款:8308] 开始排队...
小曾[存款:5211] 开始排队...
小游[存款:8264] 开始排队...
小丽[存款:8383] 开始排队...
小吴[存款:7664] 开始排队...
小昊[存款:2715] 开始排队...
小周[存款:9760] 开始排队...
小郑[存款:8158] 开始排队...
小秦[存款:869] 开始排队...
小丘[存款:1806] 开始排队...
小周[存款:9760] 办理业务.
小王[存款:9535] 办理业务.
小明[存款:9296] 办理业务.
小赵[存款:8439] 办理业务.
小丽[存款:8383] 办理业务.
小朱[存款:8308] 办理业务.
小游[存款:8264] 办理业务.
小郑[存款:8158] 办理业务.
小吴[存款:7664] 办理业务.
小黄[存款:7330] 办理业务.
小刘[存款:5732] 办理业务.
小曾[存款:5211] 办理业务.
小李[存款:3912] 办理业务.
小吕[存款:3714] 办理业务.
小昊[存款:2715] 办理业务.
小丘[存款:1806] 办理业务.
小孙[存款:1421] 办理业务.
小秦[存款:869] 办理业务.
小刚[存款:765] 办理业务.
小红[存款:333] 办理业务.

常用方法

入队

public boolean add(E e) {
    return offer(e);
}
public boolean offer(E e) {
    // 若插入的元素为null,则直接抛出NullPointerException异常
    if (e == null)
        throw new NullPointerException();
    // 获取独占锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    int n, cap;
    Object[] array;
    // 扩容
    while ((n = size) >= (cap = (array = queue).length))
        tryGrow(array, cap);
    try {
        // 根据比较器,来做不同的处理
        Comparator<? super E> cmp = comparator;
        if (cmp == null)
            siftUpComparable(n, e, array);
        else
            siftUpUsingComparator(n, e, array, cmp);
        size = n + 1;
        // 唤醒等待在非空条件上的线程
        notEmpty.signal();
    } finally {
        // 释放独占锁
        lock.unlock();
    }
    return true;
}

出队

public E poll() {
    // 获取全局锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return dequeue();
    } finally {
        // 释放全局锁
        lock.unlock();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值