《Java并发编程实战》读书笔记-第5章 基础构建模块
同步容器类
同步容器类实现线程安全的方式:将所有状态封装起来,对每个公有方法使用同步,使得每一次只有一个线程可以访问。同步容器类包含:Vector、Hashtable、Collections.synchronizedXXX等
** 同步容器类的问题 **
- 复合操作原子性需要客户端来加锁控制
- 每个操作都持有一个锁,容器规模较大的情况下,持有锁时间过长,锁竞争比较激烈,会降低系统吞吐量和CPU的利用率
并发容器
ConcurrentHashMap
- 通过粒度更细的分段锁实现数据共享
- size和isEmpty等需要在整个Map上计算的方法,返回结果是预估值
- 一些常见的操作在ConcurrentMap接口中已经声明,可以直接使用。如:“若没有则添加”、“若相等则移除”、“若相等则替换”
CopyOnWriteArrayList
- 写入时复制(Copy-On-Write)的线程安全性:初始化一个事实不可变的对象。
- 迭代中不会抛出ConcurrentModificationException
- 比较适合事件通知系统:在分发通知时需要迭代已注册监听器链表,并调用每个监听器,在大多数情况下,注册和注销事件监听器的操作远远小于接受事件通知的操作
阻塞方法与中断方法
线程阻塞原因一般包含:I/O等待、加锁等待、Thread.sleep、等待另一个线程计算结果
线程阻塞状态:BLOCKED、WAITING、TIMED_WAITING
线程中断:Thread.interrupt()可以查询线程中断状态。
同步工具类
** 闭锁 **
闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态。通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态。也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成
闭锁是一次性对象,一旦进入终止状态,就不能被重置。
CountDownLatchCountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生。
CountDownLatch有一个正数计数器,countDown方法对计数器做减操作,await方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时。
FutureTask
- FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提空 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果。结果只可以在计算完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成,那么计算就不能再次启动或是取消。
- FutureTask也可作为闭锁。
** 信号量 **
- 计数信号量用来控制同时访问资源的操作数量、同时执行某个操作的数量。
- 跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(permits),允许多个线程获得许可并执行。可以用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。
- Semaphore初始值设置为1,可用作互斥锁
** 栅栏 **
- 栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生。 栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。
构建高效且可伸缩的结果缓存
public interface Computable<A, V> {
V compute(A arg) throws InterruptedException;
}
public class ExpensiveFunction implements Computable<String, BigInteger> {
@Override
public BigInteger compute(String arg) throws InterruptedException {
// 在经过长时间的计算后
return new BigInteger(arg);
}
}
public class Memoizer<A, V> implements Computable<A, V> {
private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();
private final Computable<A, V> c;
public Memoizer(Computable<A, V> c) {
this.c = c;
}
public V compute(A arg) {
Future<V> f = cache.get(arg);
if (f == null) {
Callable<V> eval = new Callable<V>() {
@Override
public V call() throws Exception {
return c.compute(arg);
}
};
FutureTask<V> ft = new FutureTask<>(eval);
f = cache.putIfAbsent(arg, ft);
if (f == null) {
f = ft;
ft.run();
}
}
try {
return f.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}
《Java并发编程实战》读书笔记-第5章 基础构建模块的更多相关文章
- Java并发编程实战 读书笔记(一)
最近在看多线程经典书籍Java并发变成实战,很多概念有疑惑,虽然工作中很少用到多线程,但觉得还是自己太弱了.加油.记一些随笔.下面简单介绍一下线程. 一 线程与进程 进程与线程的解释 个人觉 ...
- Java并发编程实战 读书笔记(二)
关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- Java多线程编程实战读书笔记(一)
多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.
- 《Java并发编程实战》第十五章 原子变量与非堵塞同步机制 读书笔记
一.锁的劣势 锁定后假设未释放.再次请求锁时会造成堵塞.多线程调度通常遇到堵塞会进行上下文切换,造成很多其它的开销. 在挂起与恢复线程等过程中存在着非常大的开销,而且通常存在着较长时间的中断. 锁可能 ...
- 《Java并发编程实战》第十六章 Java内存模型 读书笔记
Java内存模型是保障多线程安全的根基,这里不过认识型的理解总结并未深入研究. 一.什么是内存模型,为什么须要它 Java内存模型(Java Memory Model)并发相关的安全公布,同步策略的规 ...
- 《Java并发编程实战》第十二章 测试并发程序 读书笔记
并发测试分为两类:安全性测试(无论错误的行为不会发生)而活性测试(会发生). 安全測试 - 通常採用測试不变性条件的形式,即推断某个类的行为是否与其它规范保持一致. 活跃性測试 - 包含进展測试和无进 ...
- 《Java并发编程实战》第十四章 构建自己定义的同步工具 读书笔记
一.状态依赖性的管理 有界缓存实现的基类 @ ThreadSafe public abstract class BaseBoundedBuffer<E> { @GuardeBy( &quo ...
- Java并发编程实践读书笔记(5) 线程池的使用
Executor与Task的耦合性 1,除非线程池很非常大,否则一个Task不要依赖同一个线程服务中的另外一个Task,因为这样容易造成死锁: 2,线程的执行是并行的,所以在设计Task的时候要考虑到 ...
随机推荐
- 多线程——Thread类
进程(Process):“正在执行的程序”,程序进入内存运行就变成了一个进程.一个进程会产生多个线程. 多线程(Multithread):一个进程中同时存在几个执行体.单线程是按照函数的顺序执行,多线 ...
- Hbase入门(一)——初识Hbase
本文将介绍大数据的知识和Hbase的基本概念,作为大数据体系中重要的一员,Hbase弥补了Hadoop只能离线批处理的不足,支持存储小文件,随机检索.而这种特性使得Hbase对于实时计算体系的事件存储 ...
- Layer弹层(父子传值,兄弟传值)
需求:最外面列表界面点修改弹出LayerA界面,再点击LayerA界面中的选择地图坐标按钮弹出LayerB地图界面 这个过程涉及到的: 1:LayerA将坐标传给LayerB,LayerB在地图上显示 ...
- [VB.NET Tips]对于基本数据类型的提示
1.类型字符 有时需要直接量后面加上类型字符以明确指定类型,下面把常用的类型字符列出来 类型 字符 Short S Integer I Long L Decimal D Char c Single F ...
- CentOS7下LVM的基本操作
CentOS7下LVM的基本操作-创建LVM 环境 物理主机:windows10 虚拟软件:VMWare14 虚拟机:CentOS Linux release 7.6.1810 (Core) 软件环境 ...
- JAVA设计模式-动态代理(Proxy)源码分析
在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...
- JavaScript DOM 编程艺术
最近把JavaScript DOM 编程艺术这本书看完了,觉得这本书很好 深入浅出地展示了渐进增强.平稳退化.结构和样式分离等编程思想,我对书中重要的知识进行了梳理总结. 一.网页 二.JavaScr ...
- centos7 Apache开启URL重写组件并配置.htaccess实现伪静态
第一.修改httpd.conf文件 A - 在etc/httpd/conf/目录下的httpd.conf 文件,找到: LoadModule rewrite_module modules/mod_re ...
- Chrome浏览器启动报错:应用程序无法启动,因为应用程序的并行配置不正确。
因为国庆节了,难得关一次机(可能搞IT的习惯吧),结果给祖国庆祝完70寿辰之后归来,启动电脑,就打不开Chrome浏览器了,报错如下: 应用程序无法启动,因为应用程序的并行配置不正确.有关详细信息,请 ...
- BMap添加海量点数据,BMap.Point携带数据
在开发web项目的过程中使用到了百度地图,由于要在地图中画出很多点比较影响加载速度,查看官方文档,发现有提供加载海量点的功能BMap.PointCollection,用这个加快速度,但是官方文档中提供 ...