Java并发编程实践
电子工业出版社
读书笔记:
1、volatile变量理解
写入volatile变量时就像退出同步块,读取volatile变量时就像进入同步块。volatile变量使用也存在好多限制,它通常被当作完成、中断、状态的标记使用。volatile变量只保证可见性,但不保证原子性。所以自增操作就不能依赖volatile,除非只有一个线程对它进行写操作。
不能用于构建原子化的复合操作,这意味着当一个变量依赖其他变量时,或者当变量的新值依赖于旧值时,是不能用volatile变量的。
2、可重进入的理解(Reentrancy)
当一个线程请求其他线程已经占有的锁时,请求线程会被阻塞。然而内部锁是可重进入的,因此线程在试图获得自己占有的锁时,请求会成功。重进入意味着锁的请求是基于“每线程的”,而不是“每调用的”。重进入的实现是通过为每个锁关联一个请求计数和一个占有它的线程。当计数为0时,认为锁是未被占有的。线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数置为1.如果同一线程再次请求这个锁,计数将递增;每次占用线程退出同步快,计数递减,到0锁就释放。
3、Collections.synchronizedMap() 和 ConcurrentHashMap的区别
它们一样是一个哈希表,但采用了不同的锁策略:前者使用公共锁同步每一个方法,并严格的限制只有一个线程能访问容器。后者采用一个更加细化的锁机制,名叫分离锁。
前者同步提供了一个特性就是为独占的访问加锁,这在后者中并没有实现。这对于一些罕见的情况是必要的,例如原子的加入一些mapping,或者对元素进行若干次迭代,在这期间需要看到元素以相同的顺序出现。
4、CopyOnWriteList/CopyOnWriteSet 写入时复制(copy on write)原理解析
"写入时复制"容器的线程安全性来源于这样一个事实,只要有效的不可变对象被正确的发布,那么访问它将不再需要更多的同步。在每次需要修改时,它们会创建并重新发布一个新的容器拷贝,以此来实现可变性。"写入时复制"容器保留一个底层基础数据的引用。这个数组作为迭代器的起点,永远不会被修改,以尼茨对它的同步只不过为了确保数组内容的可见性。它返回的迭代器与创建时保持一致,不会考虑后续的修改。
适合对容器迭代的频率远远高于对容器修改的频率。
5、阻塞队列 与 生产-消费者模式
阻塞队列接口 BlockQueue 支持两个附加操作的Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。
BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:
| 抛出异常 | 特殊值 | 阻塞 | 超时 |
插入 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
移除 | remove() | poll() | take() | poll(time, unit) |
检查 | element() | peek() | 不可用 | 不可用 |
它的实现:LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列
PriorityBlockingQueue是按照优先级顺序排序的队列
SynchronousQueue它根本不是一个真正的队列,因为它不会队列元素维护任何存储空间,不过它维护一个线程清单。适合消费者充足的情况,它们总能为下一个任务做好准备。
6、双端队列和窃取工作
Java 6同样新增了两个容器类型,Deque(发音为deck)和BlockingDeque,它们分别扩展了Queue和BlockingQueue。Deque是一个双端队列,允许高效地在头和尾分别进行插入和移除。实现它们的是ArrayDeque和LinkedBlockingDeque。
双端队列使它们自身与一种叫做窃取工作的模式相关联。在窃取工作的设计中,每一个消费者都有一个自己的双端队列。如果一个消费者完成了自己双端队列中的全部工作,它可以偷取其他消费者的双端队列中的末尾任务,这样可以保持每个线程都保持忙碌的状态。
7、延迟周期执行工具:Timer和新的ScheduledThreadPoolExecutor的比较
在JDK5或者更高的版本中,不建议使用Timer。
原因分析:
Timer对调度的支持是基于绝对时间的,而不是相对时间的,由此任务对系统时钟的改变是敏感的;而ScheduledThreadPoolExecutor只支持相对时间。
Timer只创建唯一的线程来执行所有的Timer任务。
Timer还有一个问题在于,如果TimerTask抛出未检查的异常,Timer将产生无法预料的行为。Timer线程并不捕获异常,所以TimerTask抛出的未检查异常会终止Timer的执行,而且Timer也不会再重新恢复线程的执行,它错误的认为整个Timer都被取消了。
分享到:
相关推荐
这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的区别** - **线程** 是程序执行的最小单位,一个进程中可以有多个线程同时执行,共享同一块内存空间,通信...
读书笔记:Java并发编程之美读书笔记
### Java编程思想读书笔记 #### 一、Java与C++的区别及内存管理 在学习Java的过程中,我们常常会拿它与C++进行比较。这两门语言虽然有着相似之处,但也有许多不同点。 1. **内存管理:** - C++提供了更为底层的...
在Java并发编程中,数据的封装与访问控制、线程安全性的考量、同步机制的使用是重要的基础概念和技巧。以下是从给出的文件内容中提取出的详细知识点: 1. 数据封装与访问控制:确保内部私有数据不被轻易访问,并且...
### Java并发编程笔记 #### 实现Runnable接口与继承Thread类 在Java中,实现多线程功能主要有两种途径:一种是通过实现`Runnable`接口,另一种则是通过继承`Thread`类。这两种方式各有优劣,具体选择哪一种取决于...
读书笔记:Java并发编程之美笔记
读书笔记:实战Java高并发程序设计学习笔记
《Java并发编程实战》个人读书笔记,非常详细: 1 简介 2 线程安全性 3 对象的共享 4 对象的组合 5 基础构建模块 6 任务执行 7 取消与关闭 8 线程池的使用 9 图形用户界面应用程序 10 避免活跃性危险 11 性能与可...
读书笔记:Java并发编程之美学习记录
读书笔记:Java并发编程之美学习代码
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括可见性、发布与逸出、线程封闭、不可变性、安全发布等内容
读书笔记:《Java并发编程之美》的读书笔记
java并发编程的艺术读书笔记根据章节整理的核心内容,便于自己理解
《王者归来之Thinking in Java读书笔记》是对Bruce Eckel的经典之作《Thinking in Java》第四版的深度学习与总结。这本书是Java程序员的必备参考书,它深入浅出地阐述了Java语言的核心概念和技术,旨在帮助读者理解...
《java并发编程实战》读书笔记-第2章-线程安全性,脑图形式,使用xmind8制作 包括引言、线程安全性定义、原子性、加锁机制、使用锁保护状态、活跃性与性能等内容
读书笔记:《实战Java高并发程序设计》学习笔记
读书笔记:《实战 Java高并发程序设计》学习笔记
读书笔记:《实战Java高并发程序设计》读书笔记
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括线程安全类设计、实例封闭、线程安全性委托、现有线程安全类中添加功能和文档化同步策略等内容
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括同步容器类、并发容器类、阻塞队列和生产者消费者模式、阻塞和中断方法、同步工具类。最后是构建高效且可伸缩的结果缓存