后端并发编程操作简述 Java高并发程序设计 六类并发容器 七种线程池 四种阻塞队列

news2024/11/26 20:53:43

目录

并发集合

1. ConcurrentHashMap:

2. CopyOnWriteArrayList:

3. CopyOnWriteArraySet:

4. BlockingQueue系列:

5. ConcurrentSkipListMap 和 ConcurrentSkipListSet:

6. ConcurrentLinkedDeque:

注意事项

七种线程池

1. FixedThreadPool

2.CachedThreadPool

3.ScheduledThreadPool

4.SingleThreadExecutor

5.SingleThreadScheduledExecutor

6.ForkJoinPool

7. CustomThreadPool(自定义线程池)

四种阻塞队列

1. ArrayBlockingQueue

2. LinkedBlockingQueue

3. PriorityBlockingQueue

4. DelayQueue

综合示例

1.在实际应用中,应该确保线程池和阻塞队列的正确关闭和资源释放。

2.消费者任务中的无限循环需要额外的机制来优雅地终止,例如使用中断或额外的停止标志。

3.根据具体需求选择合适的线程池和阻塞队列实现。


并发集合

除了 ConcurrentLinkedQueue 之外, Java 还提供了多种并发集合类,以满足不同场景下的并发需求。
以下是一些常见的并发集合类:

1. ConcurrentHashMap

这是一个线程安全的哈希表实现,针对多线程环境进行了优化,以减少锁竞争从而提高性
能。
它通过分段锁(在 JDK8 之前)或 CAS Compare-And-Swap )操作(在 JDK8 及之后)来实现
高效的并发访问。
适用于多线程操作大量数据,且读操作远多于写操作的场景。

2. CopyOnWriteArrayList

这是一个线程安全的可变数组,其中所有可变操作(如添加、设置等)都是通过对底层数组
的复制来实现的。
适用于读多写少的场景,因为写操作需要复制整个数组,开销较大。
迭代器是弱一致性的,即在遍历过程中可能看不到其他线程的修改。

3. CopyOnWriteArraySet

这是一个线程安全的 Set 实现,基于 CopyOnWriteArrayList
继承了 CopyOnWriteArrayList 的线程安全性和弱一致性迭代器的特性。

4. BlockingQueue系列

这是一个支持阻塞操作的队列接口,其实现类包括 ArrayBlockingQueue
LinkedBlockingQueue PriorityBlockingQueue DelayQueue SynchronousQueue
LinkedBlockingDeque 等。
这些队列在插入和移除元素时,如果队列为空或已满,则会根据具体情况阻塞调用线程或抛
出异常。
常用于生产者 - 消费者问题,以及需要线程间协调的场景。

5. ConcurrentSkipListMap ConcurrentSkipListSet

这两个类是基于跳表( Skip List )的并发实现。
提供了快速的并发访问能力,并且支持有序的数据结构。
适用于跨多个线程共享访问的有序数据,以及在并发情况下需要排序功能的场景。

6. ConcurrentLinkedDeque

这是一个线程安全的双端队列,支持在队列的两端进行高效的插入和删除操作。
适用于需要频繁在队列两端进行操作的场景。
这些并发集合类在内部实现了必要的同步策略,确保了在多线程环境下的线程安全性。开发者可以根据
具体的需求和场景,选择合适的并发集合类来提高程序的并发性能和安全性
当然,以下是在上述代码的基础上添加了详细注释的版本,以帮助理解每个部分的作用和目的:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConcurrentWriteExample {
    // 定义线程数量和每个线程写入的次数
    private static final int NUM_THREADS = 10;
    private static final int NUM_WRITES_PER_THREAD = 100;

    // 共享资源:一个线程安全的ArrayList(实际上这里不是线程安全的,因为我们会手动添加锁)
    // 注意:如果直接使用ArrayList进行并发写入,需要外部同步机制。
    // 更推荐使用ConcurrentLinkedQueue或其他并发集合。
    private static final List<String> sharedList = new ArrayList<>();

    // 用于控制对共享资源的访问的锁
    private static final Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        // 创建一个固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS);

        // 提交多个任务到线程池
        for (int i = 0; i < NUM_THREADS; i++) {
            executorService.submit(() -> {
                // 每个任务会循环写入数据到共享列表中
                for (int j = 0; j < NUM_WRITES_PER_THREAD; j++) {
                    writeData("Data from thread " + Thread.currentThread().getId());
                }
            });
        }

        // 关闭线程池,不再接受新任务,但会继续执行已提交的任务
        executorService.shutdown();

        // 等待所有任务完成
        // 注意:在实际应用中,更推荐使用awaitTermination来等待指定时间或直到任务完成,
        // 并且要处理InterruptedException。这里的简单while循环只是为了演示。
        while (!executorService.isTerminated()) {
            // 等待所有任务完成
        }

        // 打印共享列表的大小和内容,以验证并发写入的结果
        System.out.println("Shared list size: " + sharedList.size());
        System.out.println("Shared list content: " + sharedList);
    }

    // 写入数据到共享列表的方法,使用锁来确保线程安全
    private static void writeData(String data) {
        // 获取锁,如果锁不可用,则当前线程会阻塞直到锁可用
        lock.lock();
        try {
            // 在锁的保护下,安全地向共享列表添加数据
            sharedList.add(data);
        } finally {
            // 确保无论如何都会释放锁,以避免死锁
            lock.unlock();
        }
    }
}
注释中强调了以下几点:
1. 线程数量和写入次数 :定义了将有多少线程同时运行,以及每个线程将写入多少次数据。
2. 共享资源 :虽然这里使用了 ArrayList ,但它是非线程安全的。我们通过外部添加
ReentrantLock 来确保线程安全。在实际应用中,更推荐使用 java.util.concurrent 包中的并
发集合。
3. :使用 ReentrantLock 来控制对共享资源的访问,确保同一时间只有一个线程可以写入数据。
4. 线程池 :使用 ExecutorService 来管理线程池,这样可以更高效地管理线程的生命周期和资源。
5. 任务提交 :将多个任务提交到线程池,每个任务都会执行写入操作。
6. 等待任务完成 :使用 shutdown() 方法关闭线程池,并使用 while 循环等待所有任务完成。在实
际应用中,更推荐使用 awaitTermination() 方法。
7. 打印结果 :在所有任务完成后,打印共享列表的大小和内容,以验证并发写入的结果是否正确。
请注意,虽然这个示例展示了如何使用锁来实现线程安全的并发写入,但在实际应用中,如果可能的
话,更推荐使用 java.util.concurrent 包中提供的并发集合和工具类,因为它们通常提供了更高的性
能和更好的可扩展性。

注意事项

使用 ReentrantLock 可以确保对共享资源的互斥访问,但也会引入一定的性能开销。
在实际应用中,如果可以使用 java.util.concurrent 包中的其他并发集合(如
ConcurrentHashMap CopyOnWriteArrayList 等),则可能更合适,因为这些集合已经内置
了线程安全机制。
始终注意死锁和性能问题,特别是在高并发场景下。
这个示例展示了基本的并发写入实现,但在实际应用中,可能需要根据具体需求进行更复杂的处理。
Java 中的 java.util.concurrent 包提供了丰富的线程池和阻塞队列实现,用于满足不同的并发需
求。以下是 Java 中的七种主要线程池和四种常见阻塞队列的详细举例、演示及特点说明,并附有代码
注释。

七种线程池

1. FixedThreadPool

特点:固定数量的线程池,线程数量在创建时指定,任务队列为无界链表。
示例:
// 创建一个固定大小的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

2.CachedThreadPool

特点:会根据需要创建新线程,如果空闲线程超过 60 秒则会被回收,任务队列为同步队列
(无存储能力)。

示例:

// 创建一个可缓存的线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

3.ScheduledThreadPool

特点:可以调度任务在给定的延迟后运行,或者定期执行。

示例:

// 创建一个调度线程池
ScheduledExecutorService scheduledThreadPool =
Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(() -> {
System.out.println("Task executed after delay");
}, 1, TimeUnit.SECONDS);

4.SingleThreadExecutor

特点:单线程执行器,确保任务按顺序执行,任务队列为无界链表
示例:
// 创建一个单线程的线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

5.SingleThreadScheduledExecutor

特点:单线程调度执行器,确保任务按顺序执行,且可以调度任务。
示例(基于 ScheduledThreadPool 简化):
// 实际上可以通过ScheduledThreadPool(1)来实现单线程调度
ScheduledExecutorService singleThreadScheduledExecutor =
Executors.newScheduledThreadPool(1);

6.ForkJoinPool

特点:用于执行分而治之算法的任务,适用于大量小规模任务的并行处理。

示例:
// 创建一个ForkJoinPool
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.submit(() -> {
// 分而治之的任务
});

7. CustomThreadPool(自定义线程池)

特点:通过 ThreadPoolExecutor 构造函数自定义线程池的核心线程数、最大线程数、存
活时间、任务队列等。
示例:
// 创建一个自定义的线程池
ThreadPoolExecutor customThreadPool = new ThreadPoolExecutor(
2, // 核心线程数
4, // 最大线程数
60L, // 线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<Runnable>() // 任务队列
);

四种阻塞队列

1. ArrayBlockingQueue

特点:基于数组的阻塞队列,有界, FIFO (先进先出)顺序。
示例:
BlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(10);

2. LinkedBlockingQueue

特点:基于链表的阻塞队列,可选有界或无界, FIFO 顺序,吞吐量通常高于
ArrayBlockingQueue
示例:
BlockingQueue<Integer> linkedBlockingQueue = new LinkedBlockingQueue<>();

3. PriorityBlockingQueue

特点:支持优先级的阻塞队列,无界,基于优先级(自然顺序或提供的 Comparator )进行
排序。
示例:

BlockingQueue<Integer> priorityBlockingQueue = new PriorityBlockingQueue<>();

4. DelayQueue

特点:支持延迟获取元素的阻塞队列,无界,元素只有在其延迟期满时才能被提取。
示例:
BlockingQueue<DelayedElement> delayQueue = new DelayQueue<>();
// DelayedElement 需要实现 Delayed 接口

综合示例

由于篇幅限制,这里只提供一个综合使用 FixedThreadPool ArrayBlockingQueue 的示例,并简
要说明其他线程池和队列的用法。
import java.util.concurrent.*;

public class ThreadPoolAndBlockingQueueExample {
    public static void main(String[] args) {
        // 创建一个固定大小的线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

        // 创建一个有界的阻塞队列
        BlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(10);

        // 生产者任务
        Runnable producer = () -> {
            try {
                for (int i = 0; i < 20; i++) {
                    arrayBlockingQueue.put(i); // 如果队列满了,会阻塞
                    System.out.println("Produced: " + i);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        // 消费者任务
        Runnable consumer = () -> {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    Integer value = arrayBlockingQueue.take(); // 如果队列空了,会阻塞
                    System.out.println("Consumed: " + value);
                    // 模拟任务处理时间
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        // 提交生产者任务给线程池
        fixedThreadPool.submit(producer);

        // 提交多个消费者任务给线程池(这里为了演示只提交一个,实际可以根据需要提交多个)
        fixedThreadPool.submit(consumer);

        // 注意:为了示例简洁,这里没有添加关闭线程池的代码。在实际应用中,应该在适当的时候调用 shutdown() 方法。
        // 优雅地关闭线程池
        try {
            Thread.sleep(10000); // 等待一段时间,允许生产者和消费者执行
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 关闭线程池
        fixedThreadPool.shutdown();
    }
}
注意

1.在实际应用中,应该确保线程池和阻塞队列的正确关闭和资源释放。

2.消费者任务中的无限循环需要额外的机制来优雅地终止,例如使用中断或额外的停止标志。

3.根据具体需求选择合适的线程池和阻塞队列实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2248038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《硬件架构的艺术》笔记(七):处理字节顺序

介绍 本章主要介绍字节顺序的的基本规则。&#xff08;感觉偏软件了&#xff0c;不知道为啥那么会放进《硬件架构的艺术》这本书&#xff09;。 定义 字节顺序定义数据在计算机系统中的存储格式&#xff0c;描述存储器中的MSB和LSB的位置。对于数据始终以32位形式保存在存储器…

wkhtmltopdf的安装与使用

本文来记录下wkhtmltopdf的安装与使用 文章目录 概述下载路径安装配置wkhtmltopdf 参数详解代码实现本文小结 概述 将html转为pdf的组件有很多&#xff0c;但是还没有哪一款能达到这个效果&#xff0c;其只要原因是wkhtmltopdf使用webkit网页渲染引擎开发的用来将 html转成 pdf…

241125学习日志——[CSDIY] [InternStudio] 大模型训练营 [17]

CSDIY&#xff1a;这是一个非科班学生的努力之路&#xff0c;从今天开始这个系列会长期更新&#xff0c;&#xff08;最好做到日更&#xff09;&#xff0c;我会慢慢把自己目前对CS的努力逐一上传&#xff0c;帮助那些和我一样有着梦想的玩家取得胜利&#xff01;&#xff01;&…

C++ High Performance(壹)

目录 前言 C概述 1.零开销原则 2.值语义 3.C函数中参数的含义 C必备技能 1.在函数返回值中使用auto 2.使用decltype(auto)转返回类型 3.对变量使用auto 4.常量引用 5.指针的常量传播 6.移动语义 7.资源获取与五法则 8.默认移动语义和零法则 9.将&&…

数据库的联合查询

数据库的联合查询 简介为什么要使⽤联合查询多表联合查询时MYSQL内部是如何进⾏计算的构造练习案例数据案例&#xff1a;⼀个完整的联合查询的过程 内连接语法⽰例 外连接语法 ⽰例⾃连接应⽤场景示例表连接练习 ⼦查询语法单⾏⼦查询多⾏⼦查询多列⼦查询在from⼦句中使⽤⼦查…

vue 预览pdf 【@sunsetglow/vue-pdf-viewer】开箱即用,无需开发

sunsetglow/vue-pdf-viewer 开箱即用的pdf插件sunsetglow/vue-pdf-viewer, vue3 版本 无需多余开发&#xff0c;操作简单&#xff0c;支持大文件 pdf 滚动加载&#xff0c;缩放&#xff0c;左侧导航&#xff0c;下载&#xff0c;页码&#xff0c;打印&#xff0c;文本复制&…

【zookeeper03】消息队列与微服务之zookeeper集群部署

ZooKeeper 集群部署 1.ZooKeeper 集群介绍 ZooKeeper集群用于解决单点和单机性能及数据高可用等问题。 集群结构 Zookeeper集群基于Master/Slave的模型 处于主要地位负责处理写操作)的主机称为Leader节点&#xff0c;处于次要地位主要负责处理读操作的主机称为 follower 节点…

Linux麦克风录音实战

在 Linux 上使用麦克风进行录音可以通过多种方式实现&#xff0c;包括使用命令行工具、图形界面应用程序以及编程接口。下面我将介绍几种常见的方法&#xff0c;从简单的命令行工具到使用 PortAudio 库进行编程。 一. 使用arecord命令行工具 arecord 是 ALSA&#xff08;Adva…

游戏引擎学习第23天

实时代码编辑功能的回顾 当前实现的实时代码编辑功能已经取得了显著的成功&#xff0c;表现出强大的性能和即时反馈能力。该功能允许开发者在修改代码后几乎立即看到变化在运行中的程序中体现出来&#xff0c;极大提升了开发效率。尽管目前的演示内容较为简单&#xff0c;呈现…

Oracle 数据库 IDENTITY 列

IDENTITY列是Oracle数据库12c推出的新特性。之所以叫IDENTITY列&#xff0c;是由于其支持ANSI SQL 关键字 IDENTITY&#xff0c;其内部实现还是使用SEQUENCE。 不过推出这个新语法也是应该的&#xff0c;毕竟MyQL已经有 AUTO_INCREMENT列&#xff0c;而SQL Server也已经有IDENT…

计算机网络socket编程(2)_UDP网络编程实现网络字典

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络socket编程(2)_UDP网络编程实现网络字典 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨…

2022年计算机网络408考研真题解析

第一题&#xff1a; 解析&#xff1a;网络体系结构-数据链路层 在ISO网络参考模型中&#xff0c;运输层&#xff0c;网络层和数据链路层都实现了流量的控制功能&#xff0c;其中运输层实现的是端到端的流量控制&#xff0c;网络层实现的是整个网络的流量控制&#xff0c;数据链…

AI Prompt Engineering

AI Prompt Engineering 简介 Prompt Engineering, 提示工程&#xff0c;是人工智能领域的一项技术&#xff0c;它旨在通过设计高效的提示词&#xff08;prompts&#xff09;来优化生成式 AI&#xff08;如 GPT、DALLE 等&#xff09;的输出。提示词是用户与生成式 AI 交互的核…

Windows系统电脑安装TightVNC服务端结合内网穿透实现异地远程桌面

文章目录 前言1. 安装TightVNC服务端2. 局域网VNC远程测试3. Win安装Cpolar工具4. 配置VNC远程地址5. VNC远程桌面连接6. 固定VNC远程地址7. 固定VNC地址测试 前言 在追求高效、便捷的数字化办公与生活的今天&#xff0c;远程桌面服务成为了连接不同地点、不同设备之间的重要桥…

直播实时美颜平台开发详解:基于视频美颜SDK的技术路径

视频美颜SDK作为实现实时美颜的关键技术&#xff0c;为开发者提供了高效、灵活的解决方案。本篇文章&#xff0c;小编将以“基于视频美颜SDK的技术路径”为主题&#xff0c;深入解析直播实时美颜平台的开发要点。 一、视频美颜SDK的作用与优势 视频美颜SDK是一种集成化的开发工…

量子感知机

神经网络类似于人类大脑&#xff0c;是模拟生物神经网络进行信息处理的一种数学模型。它能解决分类、回归等问题&#xff0c;是机器学习的重要组成部分。量子神经网络是将量子理论与神经网络相结合而产生的一种新型计算模式。1995年美国路易斯安那州立大学KAK教授首次提出了量子…

实现在两台宿主机下的docker container 中实现多机器通讯

基于我的实验背景 上位机&#xff1a;ubuntu 20.04 (docker humble 22.04) 下位机&#xff1a;ubuntu 22.04&#xff08;docker noetic 20.04&#xff09; 目标&#xff1a;实现在上位机中的docker container 容器的22.04环境去成功远程访问 非同网段的下位机的20.04的contai…

远程控制软件:探究云计算和人工智能的融合

在数字化时代&#xff0c;远程控制工具已成为我们工作与生活的重要部分。用户能够通过网络远程操作和管理另一台计算机&#xff0c;极大地提升了工作效率和便捷性。随着人工智能&#xff08;AI&#xff09;和云计算技术的飞速发展&#xff0c;远程控制工具也迎来了新的发展机遇…

ISUP协议视频平台EasyCVR萤石设备视频接入平台银行营业网点安全防范系统解决方案

在金融行业&#xff0c;银行营业厅的安全保卫工作至关重要&#xff0c;它不仅关系到客户资金的安全&#xff0c;也关系到整个银行的信誉和运营效率。随着科技的发展&#xff0c;传统的安全防护措施已经无法满足现代银行对于高效、智能化安全管理的需求。 EasyCVR视频汇聚平台以…

C#基础上机练习题

21.计算500-800区间内素数的个数cn&#xff0c;并按所求素数的值从大到小的顺序排列&#xff0c;再计算其间隔加、减之和&#xff0c;即第1个素数-第2个素数第3个素数-第4个素数第5个素数……的值sum。请编写函数实现程序的要求&#xff0c;把结果cn和sum输出。 22.在三位整数…