阻塞队列的介绍和简单实现——多线程编程简单案例[多线程编程篇(4)]

多线程编程:阻塞队列介绍与简单实现

目录

前言

阻塞队列

 阻塞队列相比普通队列的优势

1.天然线程安全

2.实现生产者-消费者模型更加简单

3.自动等待与唤醒

 生产者-消费者模型

 JAVA标准库中的阻塞队列

阻塞队列的简单实现

前言

在现代软件开发中,多线程编程能力已经成为程序员必须掌握的一项核心技能。随着计算机硬件的不断升级,单核CPU早已无法满足复杂应用的性能需求,多核并行运算已成为主流。而多线程正是实现资源最大化利用、任务高效并行执行的基础手段。

而本博客是笔者多线程编程的第四篇博客!

前三篇URL在此:

如何简单的去使用jconsloe 查看线程 (多线程编程篇1)_java jconsloe-优快云博客

浅谈Thread类及常见方法与线程的状态(多线程编程篇2)_thread.join() 和thread.get()-优快云博客

多线程编程的简单案例——单例模式[多线程编程篇(3)]-优快云博客

 笔者将继续介绍和分享学习多线程编程时遇见过的简单案例, 希望读者们通过这些简单案例能加深对于多线程编程的理解

在本篇博客中,笔者将会分享两个知识点:

1.阻塞式队列

2.生产者消费者模型

为什么分享呢

其实原因很简单:根据资料显示,阻塞式队列,是多线程编程里非常经典、非常实用的模型。在实际开发中,无论是任务调度、生产者消费者,还是定时触发某些功能,模型几乎无处不在。

可以说:理解它,就等于掌握了并发编程的一块基础地基。

那么,让我们开始介绍阻塞队列吧!!!!

博客中出现的参考图都是笔者手画的,代码示例也是笔者手敲的!影响虽小,但请勿抄袭

阻塞队列

首先我们要明白,阻塞队列作为一种数据结构,阻塞只是定语,它终究是一种队列,作为队列,它也同样遵守"先进先出"的规则

但它与一般的队列又有不同,它拥有以下的特征:

1.当队列满的时候 , 继续入队列就会阻塞 , 直到有其他线程从队列中取走元素 .
2.当队列空的时候 , 继续出队列也会阻塞 , 直到有其他线程往队列中插入元素 .

你可以理解为一个传送带

  • 一边的工人(线程)往上传送包裹  -> put()

  • 另一边的工人(线程)从传送带上取包裹 -> take()

如果传送带满了,送货的工人只能在原地等着;如果传送带空了,取货的工人也得站着干等。

 阻塞队列相比普通队列的优势

结合网上各类资料说明,我大致总结出了那么三点

1.天然线程安全

普通队列在多线程场景下,容易出现数据错乱、并发冲突,需要我们手动加锁,编写复杂的同步逻辑。而阻塞队列内部已经实现了线程安全机制,不需要我们操心锁的问题,简化开发,避免Bug

举个例子:下面的代码演示了在多线程环境下使用普通队列,可能出现的问题

import java.util.LinkedList;
import java.util.Queue;

public class NormalQueueTest {
    static Queue<Integer> queue = new LinkedList<>();

    public static void main(String[] args) throws InterruptedException {
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                queue.add(i); // 非线程安全,可能抛异常
            }
        });

        Thread consumer = new Thread(() -> {
            int count = 0;
            while (count < 10000) {
                Integer val = queue.poll(); // 可能返回 null,导致数据丢失
                if (val != null) {
                    count++;
                }
            }
        });

        producer.start();
        consumer.start();
        producer.join();
        consumer.join();

        //检查队列是否为空、数量是否一致
        System.out.println("剩余元素数量:" + queue.size());
        System.out.println("主线程走到这里了?");
    }
}

笔者使用两个线程,一个负责生产数据 producer,另一个负责消费数据 consumer

生产线程尝试向队列中添加 10,000 个整数;

消费线程尝试从队列中取出 10,000 个元素;

期望结果: 所有数据被完整消费,最终队列应为空,输出结果应为:


                
评论 81
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值