序文:
如果你没有时间阅读这本,那你就来对地方了。小编会将每一章刨去废话,取其精华。分享给大家。如果觉得可以请不要忘了关注小编。我会定期跟新java 中的经典书籍。
正文:
第四章:基础构建模块
1.同步容器类:实现的方式-将它们的状态封装起来,并对每个公有方法都进行同步使得每次只有一个线程能访问容器的状态。
同步容器类都是线程安全的,但是如果方法在一起调用并且要先判断后修改这种,就需要额外的加锁机制来保证线程安全。(线程安全类,是每个方法都安全的操作状态,但是如果将多个方法,在多个线程中有先后调用就会产生问题--类似于原子变量多个一起就要考虑加锁一样--复合操作)
所以当要并发调用多个同步容器类中的方法的时候可以把同步容器对象作为私有锁,然后在操作。(迭代,先判断在操作这种常见的都要加锁)
2.迭代器Iterator一般没有考虑到并发修改的问题,当容器在迭代过程中被修改时表现为“及时失败”-抛出异常。
这个只是捕捉并发错误,只能作为预警指示器。并不能解决并发问题。(实现的原理就是使用,用一个计数器记录当前迭代到的索引,如果计数器被修改,那么hasnext就会报错)
这样做提升了性能,但是并不安全,只能祈求不要产生并发错误,或者可以在捕获异常的时候在执行加锁的相同操作。
3.如果加锁的代码,执行时间过程会降低程序的可伸缩性。持有锁时间长其他线程阻塞的时间就长,竞争就激烈,降低吞吐量和cpu使用率。
4.“克隆”容器:如果不希望在迭代的时候加锁,就可以拷贝容器对副本进行迭代,这样拷贝可以栈封闭(方法中)所以只有一个线程能访问。(这个适合对不变状态使用)
5.注意一些隐藏的迭代器,StringBuild.append(obj)会调用 obj的toString()方法,而容器的toString ()方法会调用每个元素的toString()方法。(这里就隐藏遍历了每个元素,还有equals,hashCode,containsAll ,removeAll,retainAll)
6.并发容器类:出现是为了改进同步容器类的性能。(例子:ConcurrentHashMap)
同步容器将所有对容器状态的访问都串行化。(只要访问这个状态就只能有一个线程)
基于散列Map,CopyOnwriteArrayList
优点:可以极大地提高伸缩性并降低风险(支持常见的复合操作,先检测后执行...)
7.Queue队列(先进先出):不阻塞的线程安全类。
8.BlockingQueue扩展了Queue,增加了阻塞的插入和获取,如果队列是空那么就线程阻塞,如果队列有界且满了那么在插入的时候阻塞。(生产者 消费者设计模式中 阻塞队列非常有用)
9.并发容器类使用场景:
在并发操作中:
ConcurrentHashMap 代替HashMap
ConcurrentSkipListMap 代替SortedMap
ConcurrentSkipListSet 代替SortedSet
CopyOnwriteArrayList 代替同步List
10.ConcurrentHashMap :
并不是每个方法都在同一锁上同步并只能有一个线程访问
使用分段锁
弱一致性(size 和 isEmpty 不准确)
11.在构建高可靠的应用程序时,有界队列是一种强大的资源管理中间:它们能抑制并防止产生过多的工作项,是应用程序在复合过载的情况下变得更加健壮。
12.SynchronousQueues:
没有存储功能,所以put 和take 至少有两个线程配合才能使用。
可以理解为一个线程put 由于没有存储只能等到另一个线程take,(一个线程take 必须等另一个线程put)
13.双端队列:Deque
适用于工作密取:有多个线程访问一个队列的时候从尾部取,从而避免阻塞等待,
14一个线程不能强制其他线程停止正在执行的操作而去执行其他线程。
15.某个方法抛出InterruptedException时,表示该方法是一个阻塞方法,如果这个方法被中断,那么它将努力提前结束阻塞状态
16.同步工具类:信号量(Semaphore) 、栅栏(Barrier)、闭锁(Latch)
17.闭锁:(CountDownLatch)
可以延迟线程的进度直到到达终止状态。(到达结束状态前,所有线程都必须等待)
例子:当一个资源初始化以后所有的线程才能执行
countDownLatch ,内置一个计数器,初始化的时候会传入count :就是如果想要停止等待所要调用 countDown 的次数。(await 可以调用多次,但是countDown必须得固定为初始化的次数,所有调用了await的线程才会继续执行)
18.信号量:(Semaphore)
用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。
内部维护了一组虚拟的许可(permit在初始化的时候指定个数)acqurie 需要一个许可,release释放一个许可。
如果初始化一个Semaphore 许可是1,那么和Synchroied 加锁差不多。
19.栅栏:(CyclicBarrier)
能阻塞一组线程只掉某个事件发生。
栅栏与闭锁的区别在于:闭锁用于等待事件,而栅栏用于等待其他线程。
领取专属 10元无门槛券
私享最新 技术干货