阻塞队列(多线程)

阻塞队列是带有阻塞功能且线程安全的队列.(即,队列为空,尝试出队列,出队列操作就会阻塞等待一直阻塞到队列不为空为止,队列为满,入队操作就会阻塞等待一直阻塞到队列不满为止.) 阻塞队列的作用之一就是可以实现生产者消费者模型,有两方面的作用1.能够让程序解耦合 2.能够实现"削峰填谷".

首先使用标准库提供的阻塞队列.

复制代码
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Demo1 {
    public static void main(String[] args){
        BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
        //消费者
        //put带有阻塞功能的入队列  take带有阻塞功能的出队列
        Thread t1=new Thread(()->{
            while(true) {
                int value;
                try {
                    value = queue.take();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("消费的:" + value);

            }
        });
        Thread t2=new Thread(()-> {
            int count=1;
            while (true) {
                try {
                    queue.put(count);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("生产的:"+count);
                count++;
            }
        });
        t1.start();
        t2.start();
    }
}
//由于对生产和消费没有限制虽然限制了队列的大小是10,所以没有体现出阻塞功能.

import java.sql.SQLOutput;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Demo2 {
    public static void main(String[] args){
        BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
        //生产者
        Thread t1=new Thread(()->{
            int count=1;
            while(true){
                try {
                    queue.put(count);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("生产者:"+count);
                count++;
            }
            //如果对消费者的速度进行限制,那么会使阻塞队列满

        });
        //消费者
        Thread t2=new Thread(()->{
            int value;
            while(true){
                try {
                    value=queue.take();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("消费者:"+value);
            }
        });
        //这里消费者是一秒钟消费一次,因此在进行出队列的时候会发生阻塞
        //且队列中只有10个元素.
        t1.start();
        t2.start();
    }
}

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Demo3 {
    public static void main(String[] args){
        BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
        Thread t1=new Thread(()->{
            int count=1;
           while(true) {
               try {
                   queue.put(count);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               System.out.println("生产者:"+ count);
               count++;
           }
        });
        Thread t2=new Thread(()->{
            int value;
            while(true){
                try {
                    value=queue.take();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("消费者:"+value);
            }
        });
        //这一次是没有对生产者进行限制,因此消费者的节奏会跟着生产者.
        t1.start();
        t2.start();
    }
}

接下来自己实现一个带有阻塞功能的队列.

复制代码
//自己实现阻塞队列
class MyblockingQueue{
    //自己实现阻塞队列
    //设置一个队列是存储整形的
    private int[] elems=null;
    //[head,tail)
    //head是头结点,tail是尾结点
    //开始的时候,头结点和尾结点都是0,size也是0
    private int head=0;
    private int tail=0;
    private int size=0;
    //构造方法
    public MyblockingQueue(int capacity){
        elems=new int[capacity];
    }
    //下面写入队列操作
    void put(int elem) throws InterruptedException {
        //首先要判断队列是否满
        synchronized(this) {
            while (size >= elems.length) {
                this.wait();
                //如果队列满了就要进行阻塞操作
                //一定要进行返回等待,等待出队列操作的执行
                return;
            }
            //队列没有满入队列时
            //尾结点指向的空间没有存储元素
            elems[tail] = elem;
            tail++;
            if (tail >= elems.length) {
                tail = 0;
                //到达了队列的末尾就要回到开头
            }
            size++;
            this.notify();
        }
    }
  //出队列操作
    int take() throws InterruptedException {
        synchronized(this) {
            //还是要先判断队列是否是空,如果为空,就要阻塞等待
            while (size == 0) {
                this.wait();
                return -99999;
            }
            //出队列操作
            int result = elems[head];
            head++;
            if (head >= elems.length) {
                head = 0;
            }
            size--;
            this.notify();
            return result;
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        MyblockingQueue tt=new MyblockingQueue(10);
        Thread t1=new Thread(()->{
            int count=0;
           while(true){
               try {
                   tt.put(count);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               System.out.println("生产者: "+count);
               count++;
           }
        });
        Thread t2=new Thread(()->{
           int value;
           while(true){
               try {
                   value=tt.take();
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               System.out.println("消费者: "+value);
           }
        });
        t1.start();
        t2.start();
    }

}
相关推荐
MarkHard1231 小时前
如何利用redis使用一个滑动窗口限流
数据库·redis·缓存
hdsoft_huge1 小时前
Java & Spring Boot常见异常全解析:原因、危害、处理与防范
java·开发语言·spring boot
风中的微尘2 小时前
39.网络流入门
开发语言·网络·c++·算法
雨白2 小时前
Java 多线程指南:从基础用法到线程安全
android·java
Hungry_Shark2 小时前
IDEA版本控制管理之使用Gitee
java·gitee·intellij-idea
赛姐在努力.2 小时前
《IDEA 突然“三无”?三秒找回消失的绿色启动键、主菜单和项目树!》
java·intellij-idea
未来之窗软件服务2 小时前
幽冥大陆(二)RDIFSDK 接口文档:布草洗涤厂高效运营的技术桥梁C#—东方仙盟
开发语言·c#·rdif·仙盟创梦ide·东方仙盟
猎板PCB黄浩2 小时前
从废料到碳减排:猎板 PCB 埋容埋阻的绿色制造革命,如何实现环保与性能双赢
java·服务器·制造
ZzzK,2 小时前
JAVA虚拟机(JVM)
java·linux·jvm
西红柿维生素2 小时前
JVM相关总结
java·jvm·算法