ArrayBlockingQueue、LinkedBlockingQueue区别?

前言

本篇文章首先对阻塞队列中最常用的两个队列ArrayBlockingQueue、LinkedBlockingQueue做一个大致介绍,接着介绍使用阻塞队列实现生产者-消费者模式。

ArrayBlockingQueue

ArrayBlockingQueue是接口BlockingQueue的阻塞实现队列之一。基于数组实现的一个阻塞队列,在创建对象时必须制定容量大小。并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列。它能够实现插入和取出的阻塞方法put()和take()方法其实也是通过使用通知模式来实现。查看源码就可以知道ArrayBlockingQueue生产者方放入数据、消费者取出数据都是使用同一把重入锁,这就两者无法真正的实现生产者和消费者的并行。

LinkedBlockingQueue

LinkedBlockingQueue也是接口BlockingQueue的阻塞实现队列之一。基于链表实现的一个阻塞队列,在创建对象时如果不指定容量大小,则默认大小为Integer.MAX_VALUE,所以要注意一个问题,如果初始化时没有指定容量,生产者放入元素远大于消费者取出元素的速度时,那么生产的元素一直在链表中存在,这会对内存造成很大压力。由于是基于链表的,所以生产者每次放入元素会构造一个新节点对象,在大量并发的情况下可能会对系统GC造成一定影响,而ArrayBlockingQueue不存在这种情况。LinkedBlockingQueue同样是使用通知模式来实现。相对于ArrayBlockingQueue,LinkedBlockingQueue生产者和消费者分别使用两把重入锁来实现同步,所以可以提高系统的并发度。

总结

  ArrayBlockingQueue LinkedBlockingQueue
阻塞实现方法 通知模式实现 通知模式实现
有界无界? 有界,构造器必须初始化容量 有界,构造器可以不初始化容量,默认为Integer.MAX_VALUE
插入取出元素是否会创建或销毁元素 不会
生产者消费者锁的使用情况 共用一把锁 各自使用独立的锁

ArrayBlockingQueue实现生产-消费者模式

ArrayBlockingQueue实现生产-消费者模式代码如下

package thread;


import java.util.concurrent.*;

public class MyThread {
    // 定义阻塞队列大小
    private static final int maxSize = 5;
    public static void main(String[] args){
        ArrayBlockingQueue queue = new ArrayBlockingQueue(maxSize);
        new Thread(new Productor(queue)).start();
        new Thread(new Customer(queue)).start();
    }
}

class Customer implements Runnable {
    private BlockingQueue queue;
    Customer(BlockingQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        this.cusume();
    }

    private void cusume() {
        while (true) {
            try {
                int count = (int) queue.take();
                System.out.println("customer正在消费第" + count + "个商品~v~");
                // 只是为了方便观察输出结果
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Productor implements Runnable {
    private BlockingQueue queue;
    private int count = 1;
    Productor(BlockingQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        this.product();
    }
    private void product() {
        while (true) {
            try {
                queue.put(count);
                System.out.println("生产者正在生产第" + count + "个商品");
                count++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
输出结果
customer正在消费第1个商品~v~
生产者正在生产第1个商品
生产者正在生产第2个商品
生产者正在生产第3个商品
生产者正在生产第4个商品
生产者正在生产第5个商品
生产者正在生产第6个商品
customer正在消费第2个商品~v~
生产者正在生产第7个商品
customer正在消费第3个商品~v~
生产者正在生产第8个商品
customer正在消费第4个商品~v~
生产者正在生产第9个商品

生产消费者模式还可以通过使用wait()-notify()来实现。

实现代码见连接:用 wait-notify解决生产者-消费者问题

 

 

参考文献

[1]https://wsmajunfeng.iteye.com/blog/1629354

[2]https://blog.csdn.net/g893465244/article/details/52511666

你可能感兴趣的:(java多线程)