JDK的并发容器
Map类
HashMap,位于java.util包下,是不安全的,可以采用Collections工具类来进行包装
public static Map m = Collections.synchronizedMap(new HashMap());
这样得到的Map就是线程安全的,但是在多线程环境下性能表现不是很好,因为它是通过加锁的方式,会导致其他线程对Map的操作全部等待
ConcurrentHashMap,位于java.util.concurrent包下,线程安全,采用锁分段技术,将大锁换小锁,提高性能
List类
- 基于数组实现的:ArrayList和vector,内部都是利用数组实现的,但ArrayList是不安全的,而vector是安全的,并且,其子类stack也是线程安全的,同样
- 基于链表实现的:LinkedList——既实现了List接口,也实现了Deque接口,Deque接口不仅可以当做双端队列,还可以当做栈来使用,同样也是线程不安全的,对于这几个不安全的List类,均可以使用Collections工具类相应的synchronizedXXX()方法来实现线程安全
- 高效读写的队列:ConcurrentLinkedQueue,使用链表作为数据结构,高并发环境下性能表现最好的队列
数据共享通道:BlockingQueue
- 线程A和线程B互相通信的一种手段,我们希望线程A能够通知线程B,同时线程A不需要知道线程B的存在,使得整个系统低耦合,当系统升级线程B为线程C的时候,可以不用修改线程A
- 利用数据共享通道BlockingQueue能够实现
- 阻塞队列可以让服务线程在队列为空的时候等待,当有新的任务进入队列后,再自动将服务线程唤醒去处理相应的任务
以put()方法为例,队列压入元素有offer()方法和put()方法,对于offer()方法,如果队列已满,就会立即返回false,而put()方法一旦满了,则会等待,直到队列中有空闲的位置。底层实现使用了重入锁和Condition.
final ReentrantLock lock; private final Condition notEmpty; private final Condition notFull; take()过程: public E take() throws InterruptException{ final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try{ while(count==0) notEmpty.await(); return extract(); } finally{ lock.unlock(); }} 当队列为空时,要求当前线程等待,当队列中有新元素时,该线程会得到一个通知,继续执行 private void insert(E x){ items[putIndex] = x; putIndex = inc(putIndex); ++count; notEmpty.signal(); } 新元素入队后,通知等待在notEmpty上的线程,让他们继续执行。