Java-阻塞队列

目录

1.阻塞队列是什么

1.1定义

1.2标椎库中的阻塞队列

1.3阻塞队列的具体实现

2.生产者-消费者模型

2.1定义

2.2实现


序列:多线程 - 009

1.阻塞队列是什么

1.1定义

阻塞队列:一种特殊的队列,也遵守“先进先出”的原则。

阻塞队列是一种线程安全的数据结构,并且具有如下特性:

  • 当队列为空时,继续出队列,就会发生阻塞,直到其他的线程往队列中插入元素;
  • 当队列为满时,继续入队列,就会发生阻塞,直到其他的线程从队列中取出元素;

阻塞队列最大的意义就是可以用来实现“生产者 - 消费者模型”,这是一种经典的多线程开发模型。

1.2标椎库中的阻塞队列

在Java的标椎库中内置了阻塞队列,可以直接使用。

  • BlockingQueue是一个接口,真正的实现类是LinkedBlockingQueue。
  • BlockingQueue也offer()、poll()和peek()等方法,但这些方法没有阻塞特性,不建议使用。
  • put()方法用于阻塞式入队列,take()方法用于阻塞式出队列。
BlockingQueue blockingQueue = new LinkedBlockingQueue<>();
        //入队列
        blockingQueue.put("abc");
        //出队列
        blockingQueue.take();

1.3阻塞队列的具体实现

接下来,我们根据阻塞队列的性质来实现一个。

  • 通过“循环队列”的方式来实现;
  • 使用synchronized进行加锁控制;
  • put()插入元素的时候,判定如果队列满了,就进行wait();
  • take()取出元素的时候,判定如果队列为空,就进行wait();
class MyBlockingQueue{
    //此处这里的最大长度,也可以指定构造方法,由构造方法的参数来制定
    private String[] data = new String[1000];
    //队列的起始位置
    private volatile int head = 0;
    //队列结束位置的下一个位置
    private volatile int tail = 0;
    //队列中有效元素的个数
    private volatile int size = 0;
    Object locker = new Object();//创建锁对象
    //提供核心方法,入队列和出队列
    public void put(String elem) throws InterruptedException {//入队列
        synchronized (locker){
            while (size == data.length){//while循环持续判断唤醒之后队列是否为满,为满则等待,直到不为满为止
                //队列满了
                //如果队列的元素满了,还要继续插入元素,则会阻塞
                locker.wait();
            }
            //队列没有满,真正往里边添加元素
            data[tail] = elem;
            tail++;
            //如果tail自增之后,到达了数组的末尾,这个时候就需要让他回到开头(环形队列)
            if (tail == data.length){
                tail = 0;
            }
            size++;
            //这个notify()用来唤醒take中的wait方法
            locker.notify();
        }
    }
    public String take() throws InterruptedException {//出队列
        synchronized (locker){
            while (size == 0){//while循环持续判断唤醒之后队列是否为空,为空则等待,直到不为空为止
                //队列空了
                locker.wait();//队列为空,会进行阻塞等待
            }
            //如果队列不为空,就可以把队首元素(head位置)删除掉,并进行返回
            String ret = data[head];
            head++;
            if (head == data.length){
                head = 0;
            }
            size--;
            //这个notify()是用来唤醒put中的wait方法
            locker.notify();
            return ret;
        }
    }
}

2.生产者-消费者模型

2.1定义

生产者-消费者模型就是通过一个容器来解决生产者和消费者的强耦合问题。

生产者和消费者彼此之间不直接通讯,而是通过阻塞队列的方式通讯。生产者生产数据之后,直接扔给阻塞队列;消费者不找生产者要数据,而是从阻塞队列中取数据。

2.2实现

根据以上的介绍,生产者-消费者模型具体实现如下:

/**
 * 生产者-消费者模型
 */
public class ShengchanXiaofei {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue blockingQueue = new LinkedBlockingQueue<>();//创建阻塞队列
        Thread producer = new Thread(()->{//生产者
            //随机生产1000以内的整数,并且存储到阻塞队列中,每隔一秒生产一个
            Random random = new Random();
            while (true){
                try {
                    int temp = random.nextInt(1000);
                    System.out.println("生产元素:" + temp);
                    blockingQueue.put(temp);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"生产者");
        producer.start();
        Thread customer = new Thread(()->{//消费者
            //依次打印阻塞队列中的元素,队列中无元素时则阻塞等待,直到生产者生产出元素为止
            while (true){
                try {
                    int temp = blockingQueue.take();
                    System.out.println("消费元素:" + temp);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"消费者");
        customer.start();
    }
}

你可能感兴趣的:(JavaEE,(初阶),java,开发语言,java-ee)