Java并发编程实践(2)

来源:互联网 发布:淘宝货到付款怎么买 编辑:程序博客网 时间:2024/05/21 11:08

1、同步容器类
HashMap和Hashtable的区别;HashMap底层继承AbstractMap抽象类,并实现Map接口,Hashtable底层继承Dictionary类并实现Map接口;HashMap初始话大小为16而Hashtable初始化大小为11,HashMap是非线程安全的而Hashtable是线程安全的,其底层实现采用了同步机制,因此在单线程环境中Hashtable的访问速度比HashMap要慢,HashMap的key和value能够为null,Hashtable的key和value不能为null。HashMap和Hashtable的低层数据结构都为散列表,他们都是通过分离链表法来解决hash冲突的问题。
解决hash冲突的方法:1)分离链表法,在每个桶位后面有一个单向的链表结构,当hash冲突时,将元素添加到当前桶位,链表其它元素形成链表结构;2)开放地址法a、线性探测法根据元素的hash值确定桶位,当发生hash冲突时,寻找当前位置的下一个位置,直到找到一个为空的桶位,容易发生一次聚焦情况,即元素占据的桶位形成一个区块,使插入新的元素时花费的时间增多;b、平方探测法:插入新元素时若发生hash冲突,则查找下一个离当前桶位距离为i的平法的桶位,直到找到空桶位;3)再散列、当散列表的容量达到某个装载因子或出现插入失败时,建立一个新的散列表大小为原来的两倍,然后重新散列;
2、ConcurrentHashMap并发容器
ConcurrentHashMap是一种线程安全的基于散列的Map,其底层实现采用了分段锁,细化了锁的粒度,使多个线程能并发的访问该容器,相比Hashtable而言,访问性能更好;
3、CopyOnWriteArrayList
“写时复制”该容器能够取代线程安全的Vector,再迭代过程中其不用加锁同步。线程写入时会复制底层数组创建一个新的数组。比如add操作时,当前线程获得一个显示锁,用于防止多个线程执行add操作时,创建多个数组,浪费内存,然后该线程复制底层数组在新数组基础上进行写操作,写操作完成后线程释放锁,将底层数组的应用指向新的数组。这个过程如果有其他线程对数组进行迭代操作,它实际上是线程安全的,不会抛出ConcurrentModifiedException异常,不必考虑其它线程修改操作的影响。
4、阻塞队列(BlockingQueue)
阻塞队列提供可阻塞的get和put方法,当队列为空时,take方法一直处于阻塞状态直到队列中有元素可用,当队列满时,put方法一直处于阻塞状态,直到有空间可用。阻塞队列支持生产者-消费者模式,该模式将“找出需要完成的工作”和“执行工作”两部分分离开来,实现生产者和消费者的解耦。ArrayBlockingQueue,读写线程不能同时进行,读写采用同样的显示锁;LinkedBlockingQueue,读写进程能够同时进行,该类细化了锁的粒度put和take分别采用显示锁进行同步,使线程能够同时对队列进行读写操作。
5、信号量(Semaphore)、栏栅(CyclicBarrier)、闭锁(CountDownLatch)
CountDownLatch:闭锁相当于一扇门,当线程执行await方法时,线程被阻塞,countDown方法是一个计数器,当计数器为0时,被阻塞的线程重新处于运行状态;CyclicBarrier和闭锁功能类似,但其能够再次使用;信号量(Semaphore)控制同时访问某个特定资源的操作数量,acquire方法获得权限,release方法释放权限,其类似于有界阻塞对列。

原创粉丝点击