并发编程
一、简介
并发编程主要分为如下四个大部分:
- 并发容器
- 并发队列
- 并发工具类
- Executor线程连接池
二、并发容器
- 并发类容器是专门针对多线程并发而设计,使用锁分段技术,只对操作的位置的笑区间进行同步操作,但是其他没有操作的区间其他线程仍然可以访问,即降低了锁的粒度,提高了程序的吞吐量。
- 常见的普通容器,和其对应的同步容器以及并发容器:
普通容器 同步容器 并发容器 说明 ArrayList Vector CopyOnWriteArrayList 记录添加顺序的集合 HashSet - CopyOnWriteArraySet 不记录添加顺序的集合 TreeSet - ConcurrentSkipListSet 不记录添加顺序且不重复的集合 HashMap Hashtable ConcurrentHashMap 不记录添加顺序的键值集合 TreeMap - ConcurrentSkipListMap 按照键的自然顺序排序
三、并发队列
并发队列 | 说明 |
---|---|
ConcurrentLinkedQueue | 一个基于链表的无界线程安全队列。此队列按照 FIFO原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列获取操作从队列头部获得元素。当多个线程共享访问一个公共 Collection 时,ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许使用 null 元素。与同步容器Queue对应 |
LinkedBlockingQueue | 基于链表实现的一个阻塞队列 |
ArrayBlockingQueue | 基于数组实现的一个阻塞队列 |
PriorityBlockingQueue | 根据优先级排序一个阻塞队列 |
四、并发工具类
- 并发工具类都是基于底层的AQS(AbustactQueuedSynchronizer)实现的,常见的并发工具类如下:
并发工具类 说明 CountDownLatch 一组线程在阻塞的主线程上相互等待,直到所有线程都完成自己的任务后主线程才继续执行,主线程调用CountDownLatch的await方法阻塞,每个线程内部调用CountDownLatch的countDown方法,直到所有线程都调用了这个方法 CyclicBarrier CountDownLatch只可以等待一次,而CyclicBarrier是CountDownLatch多等到版本,不同的是,每个线程中都调用CyclicBarrier的await方法 Semaphore 主要用来控制并发量 Exchanger 两条线程在同步点进行数据交换
五、Executor线程连接池
- 线程连接池是JDK提供的一套用于节约系统资源的方案,提供了四中不同类型的线程池,如下表:
线程连接池 说明 FixedThreadPool 建议使用的线程池。构造参数传递的数字作为核心线程数和最大线程数,即核心线程数等于最大线程数,如果线程池中有空闲线程那就把任务交给空闲线程,如果没有则需要看线程数是否已满,如果没有满,就创建一个新的线程执行任务,如果线程池满了,则把任务交给等待队列LinkedBlockingQueue,如果队列已经满了,则把任务交给RejectedExecutionHandler拒绝任务,默认是AbortPolicy CachedThreadPool 只要没有线程执行任务,就可以无限制的创建,除非已经到了最大线程数,而默认情况下,最大线程数是Integer.MAX_VALUE,即int的最大值,要是用在服务器上,只要用户小规模,就可以把服务器压趴下,服务器上千万不能用,除非重新设置参数 ScheduledThreadPool 可以定时执行任务的线程池 SingleThreadExecutor 单线程执行器,即线程池中永远只有一条线程,这里就不是线程池了
死锁的两种展现形式:
- 两个线程都持有对方需要的资源,都不释放;
- 一个线程持有锁,然后挂掉了,锁没有得到释放,其他线程永远无法获取到资源而一直处于等待状态;
网友评论