java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java阻塞队列

Java基于阻塞队列实现生产者消费者模型示例详解

作者:兜里有颗棉花糖

这篇文章主要介绍了Java基于阻塞队列实现生产者消费者模型,阻塞队列的特点就是阻塞两个字,阻塞功能使得生产者和消费者两端的能力得以平衡,当有任何一端速度过快时,阻塞队列便会把过快的速度降下来,感兴趣的朋友可以参考下

一、阻塞式队列

什么是阻塞式队列(有两点):

二、生产者消费者模型

什么是生产者消费者模型

生产者消费者模型是常见的多线程编程模型,可以用来解决生产者和消费者之间的数据交互问题。

阻塞队列的最主要的一个目的之一就是实现生产者消费者模型(基于阻塞队列实现),生产者消费主模型是处理多线程问题的一种方式。

生产消费者模型的优势

生产者消费主模型的优势:针对分布式系统有两个优势,一个是解耦合(耦合我们可以理解为依赖程度)、另一个是削峰填谷。

阻塞队列只是一个数据结构,如果我们把这个数据结构单独实现称了一个服务器程序,并且使用单独的主机或者主机群来进行部署的话,此时阻塞式队列就进化成了消息队列。而在Java标准库中已经实现了阻塞队列,并且实现了三种阻塞队列的实现方式:

三、生产者消费者举例代码

生产消费者模型代码如下(基于阻塞式队列):

import java.util.concurrent.BlockingQueue;
  import java.util.concurrent.LinkedBlockingQueue;
// 生产消费者模型——阻塞队列
public class Demo20 {
    public static void main(String[] args) {
        // 创建一个阻塞队列来作为交易场所
        BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
        Thread t1 = new Thread(() -> {
            int count = 0;
            while(true) {
                try {
                    queue.put(count);
                    System.out.println("生产元素:" + count);
                    count++;
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(() -> {
            while(true) {
                while(true) {
                    try {
                        Integer n = queue.take();
                        System.out.println("消费元素:" + n);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t1.start();
        t2.start();
    }
}

代码运行结果如下:

四、基于阻塞式队列实现生产者消费者模型

现在,我们自己来基于循环队列来实现阻塞式队列。注意我们这里实现的阻塞队列是基于数组、基于循环队列的阻塞队列。

我们在实现阻塞队列的时候有以下几点需要注意:

代码如下:

class MyBlockQueue {
    // 使用string类型的数组来保存元素,我们假设这里只存string
    private String[] items = new String[1000];
    //head表示指向队列的头部
    volatile private int head = 0;
    volatile private int tail = 0;
    volatile private int size = 0; // size表示元素个数
    private Object locker = new Object();
    public void put(String elem) throws InterruptedException {
        synchronized(locker) {
            while(size >= items.length) {
                //队列已满
                locker.wait();
                //return;
            }
            items[tail] = elem;
            tail++;
            if(tail >= items.length) {
                tail = 0;
            }
            //tail++和下面的if判断可以替换成tail = (tail + 1) % (items.length)
            //但是站在CPU的角度来看,其实还是简单的if判断比较快
            size++;
            locker.notify(); // 用来唤醒队列为空的阻塞情况
        }
    }
    //出队列
    public String take() throws InterruptedException {
        synchronized(locker) {
            while(size == 0) {
                locker.wait();
            }
            String elem = items[head];
            head++;
            if(head >= items.length) {
                head = 0;
            }
            size--;
            //使用notify来唤醒队列阻塞满的情况
            locker.notify();
            return elem;
        }
    }
}
public class Demo21 {
    public static void main(String[] args) {
        // 创建两个线程分别表示消费者和生产者
        MyBlockQueue queue = new MyBlockQueue();
        Thread t1 = new Thread(() -> {
           int count = 0;
           while(true) {
               try {
                   queue.put(count + "");
                   System.out.println("生产元素: " + count);
                   count++;
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        Thread t2 = new Thread(() -> {
            while(true) {
                try {
                    String count = queue.take();
                    System.out.println("消费元素: " + count);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
        t2.start();
    }
}

以上就是Java基于阻塞队列实现生产者消费者模型示例详解的详细内容,更多关于Java阻塞队列的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文