Netty的并发编程实践4:线程安全类的应用
在JDK1.5的发行版本中,Java平台新增了java.util.concurrent,这个包中提供了一系列的线程安全集合、容器和线程池,利用这些新的线程安全类可以极大地降低Java多线程编程的难度,提升开发效率。
新的并发编程包中的工具可以分为如下4类。
◎ 线程池Executor Framework以及定时任务相关的类库,包括Timer等。
◎ 并发集合,包括List、Queue、Map和Set等。
◎ 新的同步器,例如读写锁ReadWriteLock等。
◎ 新的原子包装类,例如AtomicInteger等。
在实际编码过程中,我们建议通过使用线程池、Task(Runnable/Callable)、原子类和线程安全容器来代替传统的同步锁、wait和notify,以提升并发访问的性能、降低多线程编程的难度。
下面,针对新的线程并发包在Netty中的应用进行分析和说明,以期为大家的学习和应用提供指导。
首先看下线程安全容器在Netty中的应用。NioEventLoop是I/O线程,负责网络读写操作,同时也执行一些非I/O的任务。例如事件通知、定时任务执行等,因此,它需要一个任务队列来缓存这些Task。它的任务队列定义如图21-12所示。
图21-12 线程任务队列定义
它是一个ConcurrentLinkedQueue,我们看它的API说明,如图21-13所示。
图21-13 ConcurrentLinkedQueue线程安全文档
DOC文档明确说明这个类是线程安全的,因此,对它进行读写操作不需要加锁。下面我们继续看下队列中增加一个任务,如图21-14所示。
图21-14 ConcurrentLinkedQueue新增Task
读取任务,也不需要加锁,如图21-15所示。
图21-15 ConcurrentLinkedQueue读取Task
JDK的线程安全容器底层采用了CAS、volatile和ReadWriteLock实现,相比于传统重量级的同步锁,采用了更轻量、细粒度的锁,因此,性能会更高。合理地应用这些线程安全容器,不仅能提升多线程并发访问的性能,还能降低开发难度。
下面我们看看线程池在Netty中的应用,打开SingleThreadEventExecutor看它是如何定义和使用线程池的。
首先定义了一个标准的线程池用于执行任务,代码如下。
接着对它赋值并且进行初始化操作,代码如下。
执行任务代码如图21-16所示。
图21-16 SingleThreadEventExecutor任务执行
我们发现,实际上执行任务就是先把任务加入到任务队列中,然后判断线程是否已经启动循环执行,如果不是则需要启动线程。启动线程代码如图21-17所示。
实际上就是执行当前线程的run方法,循环从任务队列中获取Task并执行,我们看它的子类NioEventLoop的run方法就能一目了然,如图21-18所示。
如图21-19中框线内所示,循环从任务队列中获取任务并执行。
图21-17 SingleThreadEventExecutor启动新的线程
图21-18 按照I/O任务比例执行任务Task
图21-19 循环从任务队列中获取任务Task并执行
Netty对JDK的线程池进行了封装和改造,但是,本质上仍然是利用了线程池和线程安全队列简化了多线程编程。
Netty的并发编程实践4:线程安全类的应用的更多相关文章
- Netty的并发编程实践5:不要依赖线程优先级
当有多个线程同时运行的时候,由线程调度器来决定哪些线程运行.哪些等待以及线程切换的时间点,由于各个操作系统的线程调度器实现大相径庭,因此,依赖JDK自带的线程优先级来设置线程优先级策略的方法是错误和非 ...
- Netty的并发编程实践2:volatile的正确使用
长久以来大家对于volatile如何正确使用有很多的争议,既便是一些经验丰富的Java设计师,对于volatile和多线程编程的认识仍然存在误区.其实,volatile的使用非常简单,只要理解了Jav ...
- Netty的并发编程实践1:正确使用锁
很多刚接触多线程编程的开发者,虽然意识到了并发访问可变变量需要加锁,但是对于锁的范围.加锁的时机和锁的协同缺乏认识,往往会导致出现一些问题.下面笔者就结合Netty的代码来讲解下这方面的知识. 打开F ...
- Netty的并发编程实践3:CAS指令和原子类
互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能的额外损耗,因此这种同步被称为阻塞同步,它属于一种悲观的并发策略,我们称之为悲观锁.随着硬件和操作系统指令集的发展和优化,产生了非阻塞同步,被称为 ...
- [Java 并发] Java并发编程实践 思维导图 - 第二章 线程安全性
依据<Java并发编程实践>一书整理的思维导图.
- 并发编程实践五:ReentrantLock
ReentrantLock是一个可重入的相互排斥锁,实现了接口Lock,和synchronized相比,它们提供了同样的功能.但ReentrantLock使用更灵活.功能更强大,也更复杂.这篇文章将为 ...
- 并发编程实践三:Condition
Condition实例始终被绑定到一个锁(Lock)上.Lock替代了Java的synchronized方法,而Condition则替代了Object的监视器方法,包含wait.notify和noti ...
- 【Java并发编程六】线程池
一.概述 在执行并发任务时,我们可以把任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程,只要池里有空闲的线程,任务就会分配一个线程执行.在线程池的内部,任务被插入一个阻塞队列(Blo ...
- Java并发编程实践
最近阅读了<Java并发编程实践>这本书,总结了一下几个相关的知识点. 线程安全 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任 ...
随机推荐
- 排序算法之low B三人组
排序low B三人组 列表排序:将无序列表变成有充列表 应用场景:各种榜单,各种表格,给二分法排序使用,给其他算法使用 输入无序列表,输出有序列表(升序或降序) 排序low B三人组 1. 冒泡排序 ...
- BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]
以后我也要用传送门! 题意:一些数,选择一个权值最大的异或和不为0的集合 终于有点明白线性基是什么了...等会再整理 求一个权值最大的线性无关子集 线性无关子集满足拟阵的性质,贪心选择权值最大的,用高 ...
- CF266D. BerDonalds [图的绝对中心]
D. BerDonalds time limit per test 5 seconds memory limit per test 256 megabytes input standard input ...
- vue2.0路由进阶
一.路由的模式 第一种用history方式实现,HTML5使用window.history.pushState()实现路由的切换而不刷新页面. 第二种使用hash值的方式来实现. vue2.0两种都可 ...
- 在window上安装redis
redis没有官方的windows版本,如果需要在windows安装可以下载由微软维护的redis(https://github.com/MicrosoftArchive/redis). 在这里我们采 ...
- Spring MVC的配置和使用
Spring MVC的配置和使用 笔记仓库:https://github.com/nnngu/LearningNotes Spring MVC需要的jar包 文章中 Spring MVC 使用的版本是 ...
- 线性一致性与全序广播------《Designing Data-Intensive Applications》读书笔记12
上一篇聊了聊构建分布式系统所面临的困难,这篇将着重讨论构建容错分布式系统的算法与协议.构建容错系统的最佳方法是使用通用抽象,允许应用程序忽略分布式系统中的一些问题.本篇我们先聊一聊线性一致性,以及与线 ...
- I can do it
If it doesn't challange you ,it won't change you.
- .NET平台开源项目速览(19)Power BI神器DAX Studio
PowerBI更新频繁,已经有点更不上的节奏,一直在关注和学习中,基本的一些操作大概是没问题,更重要的是注重Power Query,M函数,以及DAX的使用,这才是核心. 上个月研究了DAX的一些 ...
- 我不知道的行高——line-height
概述 对于块级元素,CSS属性line-height指定了元素内部line-boxes的最小高度. 对于非替代行内元素,line-height用于计算line box的高度. 对于替代行内元素,如bu ...