并发编程核心知识

📕我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)(进阶篇)、(架构篇)、《解密程序员的思维密码——沟通、演讲、思考的实践》作者、清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、阿里云专家博主、51CTO专家博主、产品软文专业写手、技术文章评审老师、技术类问卷调查设计师、幕后大佬社区创始人、开源项目贡献者。

📘拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、SpringMVC、SpringCloud、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RocketMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。

📙不定期分享高并发、高可用、高性能、微服务、分布式、海量数据、性能调优、云原生、项目管理、产品思维、技术选型、架构设计、求职面试、副业思维、个人成长等内容。

Java程序员廖志伟

💡在这个美好的时刻,笔者不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。

CSDN

一、并发编程知识体系

并发编程是现代计算机科学中的一个重要领域,它涉及如何让多个任务在同一时间内执行,以提高程序的响应速度和资源利用率。以下是对并发编程知识体系的详细描述,并补充其技术实现细节。

线程基础

线程是并发编程中最基本的概念,它是操作系统能够进行运算调度的最小单位。线程基础包括:

  • 线程状态:线程状态的管理通常由操作系统的线程调度器负责。线程状态包括创建、就绪、运行、阻塞、等待、超时、终止等。例如,在Java中,线程状态可以通过Thread类的方法如getState()来获取,并使用Thread.State枚举来表示不同的状态。

  • 线程属性:线程属性包括线程ID、优先级、状态、堆栈等。线程ID是操作系统分配的唯一标识符,优先级决定了线程在调度时的优先级,堆栈则是线程执行时的内存空间。

  • 线程创建:在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。继承Thread类的方式较为直接,但会带来代码复用的困难。实现Runnable接口则更加灵活,可以通过实现接口的方式将线程逻辑与线程对象分离。

线程生命周期

线程从创建到销毁会经历以下生命周期:

  • 新建状态:通过new关键字创建线程对象后,线程处于新建状态。此时线程尚未启动,也没有分配CPU资源。

  • 就绪状态:线程对象被创建后,调用start()方法,线程进入就绪状态。此时线程已经准备好执行,等待CPU调度。

  • 运行状态:就绪状态的线程获得CPU时间片,进入运行状态。线程执行完毕或被调度器切换出CPU时,将离开运行状态。

  • 阻塞状态:线程由于某些原因(如等待资源)而无法继续执行,进入阻塞状态。例如,线程在等待I/O操作完成时将进入阻塞状态。

  • 等待状态:线程调用wait()方法后,进入等待状态,直到其他线程调用notify()或notifyAll()。

  • 终止状态:线程执行完任务或调用stop()方法后,进入终止状态。此时线程将不再被调度。

线程优先级

线程优先级决定了线程在多线程环境中获取CPU资源的优先级。Java中,线程优先级分为10个等级,从1(最低)到10(最高)。线程优先级只能影响线程调度,但不能保证线程一定优先执行。线程优先级可以通过setPriority()方法设置,通过getPriority()方法获取。

守护线程

守护线程是服务线程,当所有非守护线程结束时,程序会自动退出。守护线程主要用于在后台执行一些任务,如垃圾回收器。在Java中,可以通过调用setDaemon(true)方法将线程设置为守护线程。

线程池

线程池是一种复用线程的技术,它将多个任务分配给有限的线程执行。线程池的核心参数配置包括:

  • 核心线程数:线程池维护的最少线程数。当任务数量超过核心线程数时,线程池将创建新的线程来处理任务。

  • 最大线程数:线程池能容纳的最大线程数。当任务数量超过最大线程数时,线程池将根据拒绝策略处理新任务。

  • 线程空闲时间:空闲线程在终止前等待新任务的最长时间。超过这个时间后,空闲线程将被终止。

拒绝策略

当线程池中所有线程都在执行任务时,如果还有任务提交,线程池会根据拒绝策略处理新任务。常见的拒绝策略有:

  • AbortPolicy:抛出RejectedExecutionException异常,阻止任务执行。

  • CallerRunsPolicy:调用任务的线程自己执行该任务,避免任务丢失。

  • DiscardPolicy:不执行该任务,也不抛出异常,适用于任务不重要的情况。

  • DiscardOldestPolicy:丢弃最长时间的任务,为新任务腾出空间。

工作队列类型

线程池的工作队列用于存放等待执行的任务,常见的队列类型有:

  • LinkedBlockingQueue:基于链表的阻塞队列,适用于任务数量不确定的情况。

  • ArrayBlockingQueue:基于数组的阻塞队列,适用于任务数量确定的情况。

  • SynchronousQueue:不存储元素的阻塞队列,适用于任务数量与线程数相等的情况。

同步机制

同步机制用于解决多线程并发访问共享资源时可能出现的问题,如数据不一致、死锁等。常见的同步机制有:

  • 悲观锁:假设并发冲突一定会发生,使用锁来保证线程安全。例如,Java中的synchronized关键字和ReentrantLock类。

  • 乐观锁:假设并发冲突不会发生,使用版本号或时间戳等机制来检测冲突。例如,Java中的AtomicInteger类。

  • 读写锁:允许多个线程同时读取共享资源,但写入时需要独占锁。例如,Java中的ReentrantReadWriteLock类。

  • 条件变量:允许线程在某些条件成立时才执行,否则等待。例如,Java中的Condition接口。

并发集合

Java并发集合是专为多线程环境设计的集合类,如:

  • ConcurrentHashMap:线程安全的HashMap实现,通过分段锁(Segment Locking)来提高并发性能。

  • CopyOnWriteArrayList:线程安全的ArrayList实现,适用于读多写少的场景。每次修改操作都会创建一个新的数组副本。

并发工具类

Java提供了一些并发工具类,如:

  • Phaser:支持线程间协作的工具类,可以用于实现线程间的同步和通信。

  • Exchanger:用于在线程间交换数据的工具类,可以用于实现生产者-消费者模式。

  • FutureTask:代表异步计算的结果,可以用于获取异步操作的结果。

非阻塞算法

非阻塞算法是避免使用锁的一种技术,如:

  • CAS(Compare-And-Swap):比较并交换操作,可以用于实现无锁编程。

  • Atomic类:提供原子操作的类,可以用于实现无锁编程。

无锁队列

无锁队列是使用CAS等非阻塞算法实现的线程安全队列,可以用于实现生产者-消费者模式。

并发框架

  • Netty:高性能的NIO框架,用于开发网络应用程序。Netty使用事件驱动模型,可以处理高并发网络连接。

  • Akka:基于Actor模型的并发框架,用于构建分布式、高并发系统。Akka使用无状态、无锁的Actor模型,可以处理高并发场景。

  • Disruptor:环形缓冲区,提供高性能的并发数据流处理。Disruptor使用环形缓冲区和CAS操作,可以处理高并发数据流。

二、MyBatis知识体系

MyBatis是一个基于Java的持久层框架,它简化了数据库操作,并提供了丰富的配置和扩展机制。以下是对MyBatis知识体系的详细描述,并补充其技术实现细节。

SQL映射

SQL映射是MyBatis的核心概念,它将Java对象与数据库表进行映射。SQL映射包括:

  • 映射文件:用于定义SQL语句和参数的XML文件。映射文件中定义了SQL语句、参数类型、结果映射等信息。

  • 注解映射:使用注解来定义SQL语句和参数。注解映射可以简化XML配置,提高代码可读性。

结果集映射

结果集映射将数据库表中的数据映射到Java对象中,包括:

  • 自动映射:根据Java对象的属性名和数据库表中的列名自动映射。例如,如果Java对象的属性名为"user.name",则可以自动映射到数据库表中的"username"列。

  • 显式映射:使用@Result注解或 标签显式定义映射关系。例如,可以使用@Result注解指定映射的列名和Java对象的属性名。

关联查询

关联查询用于处理多表关系,包括:

  • 一对一:使用 标签进行映射。例如,如果有一个用户表和一个地址表,可以使用一对一关系将用户和地址关联起来。

  • 一对多:使用 标签进行映射。例如,如果有一个用户表和一个订单表,可以使用一对多关系将用户和订单关联起来。

  • 多对多:使用 标签进行映射。例如,如果有一个学生表和一个课程表,可以使用多对多关系将学生和课程关联起来。

动态SQL

动态SQL允许根据条件动态生成SQL语句,包括:

  • :根据条件判断是否执行SQL片段。例如,可以使用 标签根据用户ID是否为空来决定是否包含某个条件。

  • :根据条件选择执行SQL片段。例如,可以使用 标签根据用户类型选择不同的SQL语句。

  • :遍历集合,生成SQL片段。例如,可以使用 标签遍历用户列表,为每个用户生成一条SQL语句。

OGNL表达式

OGNL(Object-Graph Navigation Language)表达式用于在MyBatis中访问对象属性,如user.name。OGNL表达式可以访问对象的属性、方法、集合等。

分支语句

分支语句用于在动态SQL中实现复杂的逻辑,如<when><otherwise>等。例如,可以使用 标签根据条件选择不同的SQL片段。

批量操作

批量操作允许一次性执行多条SQL语句,提高效率。例如,可以使用 标签遍历一个对象列表,为每个对象生成一条SQL语句,并一次性执行。

缓存机制

MyBatis提供了两级缓存机制:

  • 一级缓存:SqlSession级别的缓存,默认开启。一级缓存存储了当前SqlSession中执行的SQL语句及其结果集。

  • 二级缓存:全局缓存,需要手动开启。二级缓存存储了全局范围内缓存的SQL语句及其结果集。

自定义缓存

自定义缓存允许用户自定义缓存实现,用于更复杂的场景。自定义缓存需要实现Cache接口,并配置到MyBatis配置文件中。

代理模式

MyBatis使用代理模式来创建Mapper接口的代理实现,实现动态代理。代理模式可以隐藏实现细节,提高代码可读性和可维护性。

MapperProxy

MapperProxy是MyBatis中用于创建Mapper接口代理的实现类。MapperProxy使用JDK动态代理或CGLIB动态代理技术来创建代理对象。

插件拦截

MyBatis插件允许拦截SQL执行过程,如执行前、执行后等。插件需要实现Interceptor接口,并配置到MyBatis配置文件中。

动态代理执行流程

MyBatis使用CGLIB或JDK动态代理来创建Mapper接口的代理实现。动态代理技术可以拦截接口方法的调用,并执行相应的逻辑。

SqlSession生命周期

SqlSession是MyBatis的核心对象,它代表与数据库的会话。SqlSession的生命周期包括:

  • 创建:通过SqlSessionFactory创建SqlSession。SqlSessionFactory可以使用XML配置文件或注解配置。

  • 使用:执行SQL语句。在SqlSession中,可以执行查询、更新、删除等操作。

  • 关闭:关闭SqlSession。关闭SqlSession会释放数据库连接、关闭事务等。

执行器类型

MyBatis提供了多种执行器类型,如SimpleExecutor、ReusingExecutor、BatchingExecutor等。不同的执行器类型具有不同的性能特点。

延迟加载

延迟加载是一种优化技术,用于按需加载对象属性。例如,可以使用MyBatis的延迟加载功能,在查询用户信息时,延迟加载用户关联的订单信息。

类型处理器

类型处理器用于将数据库类型转换为Java类型。例如,可以将数据库中的字符串类型转换为Java中的String类型。

拦截器链

拦截器链用于拦截SQL执行过程,如参数处理、结果处理等。拦截器链可以自定义拦截器,并配置到MyBatis配置文件中。

方言支持

方言支持允许MyBatis根据数据库类型使用不同的SQL语句。例如,可以使用MySQL方言或Oracle方言。

通过以上对并发编程和MyBatis知识体系的详细描述,我们可以了解到这两个领域的核心概念、技术要点和应用场景。在实际开发中,合理运用这些知识可以提高程序的并发性能和数据库操作效率。

CSDN

博主分享

📥博主的人生感悟和目标

Java程序员廖志伟

📙经过多年在CSDN创作上千篇文章的经验积累,我已经拥有了不错的写作技巧。同时,我还与清华大学出版社签下了四本书籍的合约,并将陆续出版。

面试备战资料

八股文备战
场景描述链接
时间充裕(25万字)Java知识点大全(高频面试题)Java知识点大全
时间紧急(15万字)Java高级开发高频面试题Java高级开发高频面试题

理论知识专题(图文并茂,字数过万)

技术栈链接
RocketMQRocketMQ详解
KafkaKafka详解
RabbitMQRabbitMQ详解
MongoDBMongoDB详解
ElasticSearchElasticSearch详解
ZookeeperZookeeper详解
RedisRedis详解
MySQLMySQL详解
JVMJVM详解

集群部署(图文并茂,字数过万)

技术栈部署架构链接
MySQL使用Docker-Compose部署MySQL一主二从半同步复制高可用MHA集群Docker-Compose部署教程
Redis三主三从集群(三种方式部署/18个节点的Redis Cluster模式)三种部署方式教程
RocketMQDLedger高可用集群(9节点)部署指南
Nacos+Nginx集群+负载均衡(9节点)Docker部署方案
Kubernetes容器编排安装最全安装教程

开源项目分享

项目名称链接地址
高并发红包雨项目https://gitee.com/java_wxid/red-packet-rain
微服务技术集成demo项目https://gitee.com/java_wxid/java_wxid

管理经验

【公司管理与研发流程优化】针对研发流程、需求管理、沟通协作、文档建设、绩效考核等问题的综合解决方案:https://download.csdn.net/download/java_wxid/91148718

希望各位读者朋友能够多多支持!

现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!

🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 在 Android 应用开发中,开发一款仿 OPPO 手机计算器的应用是极具实践价值的任务,它融合了 UI 设计、事件处理以及数学逻辑等多方面的技术要点。当前的“最新版仿 OPPO 手机计算器--android.rar”压缩包中,提供了该计算器应用的源代码,这为开发者深入学习 Android 编程提供了宝贵的资源。 UI 设计是构建此类计算器应用的基石。OPPO 手机的计算器界面以清晰的布局和良好的用户交互体验著称,其中包括数字键、运算符键以及用于显示结果的区域等关键元素。开发者需借助 Android Studio 中的 XML 布局文件来定义这些界面元素,可选用 LinearLayout、GridLayout 或 ConstraintLayout 等布局管理器,并搭配 Button 控件来实现各个按键功能。同时,还需考虑不同分辨率屏幕和设备尺寸的适配问题,这通常涉及 Density Independent Pixel(dp)单位的应用以及 Android 尺寸资源的合理配置。 事件处理构成了计算器的核心功能。开发者要在每个按钮的点击事件中编写相应的处理代码,通常通过实现 OnClickListener 接口来完成。例如,当用户点击数字键时,相应的值会被添加到显示区域;点击运算符键时,则会保存当前操作数并设定运算类型。而对于等号(=)按钮,需要执行计算操作,这往往需要借助栈数据结构来存储操作数和运算符,并运用算法解析表达式以完成计算。 数学逻辑的实现则是计算器功能的关键体现。在 Android 应用中,开发者可以利用 Java 内置的 Math 类,或者自行设计算法来完成计算任务。基本的加减乘除运算可通过简单的算术操作实现,而像求幂、开方等复杂运算则需调用 Math 类的相关方法。此外
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值