Java并发包总结

Java 并发包

并发包中除了提供高性能的线程安全的集合对象外,还提供了很多并发场景需要的原子操作类,例如AtomicInteger,另外还提供了一些用于避免并发时资源冲突的Lock及Condition类。

ConcurrentHashMap

线程安全的HashMap的实现。

维护的是一个Segment对象数组,segment继承ReentrantLock

方法 意义
ConcurrentHashMap()
put(Object key,Object value) ConcurrentHashMap基于concurrencyLevel划分出了多个segment来对key-velue进行存储,从而避免每次put操作都得锁住整个数组。在默认的情况下,最佳情况可以允许16个线程并发无阻塞的操作集合对象
remove(Object key)
get(Object)
containsKey(Object key)
keySet().iterator()

CopyOnWriteArrayList

CopyOnWriteArrayList是一个线程安全,并且在读操作时无锁的ArrayList

在读多写少,且线程数很多的情况下,比较合适

  • CopyOnWriteArrayList()

    和ArrayList不同,创建一个大小为0的数组

  • add()

    首先使用ReentrantLock保证线程安全,另外每次都会创建一个新的Object数组,此数组的大小为当前数组大小加1,将之前数组中的内容复制到新的数组中,并将新增加的对象放到数组末尾,最后做引用切换将新创建的数组对象赋值给全局的数组对象

  • remove(E)

    首先通过ReentrantLock保证线程安全,然后删除,删除与ArrayList不同。

  • get(int)

    有可能读到脏数据

  • iterator

CopyOnWriteArraySet

基于CopyOnWriteArrayList实现,唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法

CopyOnWriteArraySet在add时每次都要进行数组遍历,因此性能会略低于CopyOnWriteArrayList.

ArrayBlockingQueue

一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素。队列的尾部 是在队列中存在时间最短的元素。新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素。

这是一个典型的“有界缓存区”,固定大小的数组在其中保持生产者插入的元素和使用者提取的元素。一旦创建了这样的缓存区,就不能再增加其容量。试图向已满队列中放入元素会导致操作受阻塞;试图从空队列中提取元素将导致类似阻塞。

  • ArrayBlockingQueue(int )
  • offer(E,long,TimeUnit)

    将指定的元素插入此队列的尾部,如果该队列已满,则在到达指定的等待时间之前等待可用的空间。

  • poll(long,TimeUnit)

    获取并移除此队列的头部,在指定的等待时间前等待可用的元素(如果有必要)。

  • put(E)

    将指定的元素插入此队列的尾部,如果该队列已满,则等待可用的空间。

  • take()

    获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)。

AtomicInteger

支持原子操作的Integer类,

  • AtomicInteger()

    创建具有初始值 0 的新 AtomicInteger。

  • AtomicInteger(int initialValue)

    创建具有给定初始值的新 AtomicInteger。

  • int addAndGet(int delta)

    以原子方式将给定值与当前值相加。

  • int decrementAndGet()

    以原子方式将当前值减 1。

  • int incrementAndGet()

    以原子方式将当前值加 1。

  • get()

    获取当前值。

  • set(int newValue)

    设置为给定值。

Executors

创建线程池

  • newFixedThreadPool(int)
  • newCachedThreadPool()
  • newSingleThreadPool()

FutureTask

可用于异步获取执行结果或取消执行任务的场景,通过传入Runnable或Callable的任务给FutureTask,直接调用其run方法或放入线程池执行,之后可在外部通过FutureTask的get异步获取执行结果。FutureTask可以确保即使调用了多次run方法,它都会执行一次Runnable或Callable任务,或者通过cancle取消FutureTask的执行。

方法 意义
FutureTask(Callable callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable。
FutureTask(Runnable runnable, V result) 创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。
boolean cancel(boolean mayInterruptIfRunning) 试图取消对此任务的执行。
protected void done() 当此任务转换到状态 isDone(不管是正常地还是通过取消)时,调用受保护的方法。
V get() 如有必要,等待计算完成,然后获取其结果。
V get(long timeout, TimeUnit unit) 如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
boolean isCancelled() 如果在任务正常完成前将其取消,则返回 true。
boolean isDone() 如果任务已完成,则返回 true。
void run() 除非已将此 Future 取消,否则将其设置为其计算的结果。
protected boolean runAndReset() 执行计算而不设置其结果,然后将此 Future 重置为初始状态,如果计算遇到异常或已取消,则该操作失败。
protected void set(V v) 除非已经设置了此 Future 或已将其取消,否则将其结果设置为给定的值。

Semaphore

一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。

方法 意义
Semaphore(int permits) 创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits, boolean fair) 创建具有给定的许可数和给定的公平设置的 Semaphore。
void acquire() 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void release() 释放一个许可,将其返回给信号量。
public boolean tryAcquire() 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。(立即获取许可)

CountDownLatch

用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。

方法 意义
void await() 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
boolean await(long timeout, TimeUnit unit) 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
void countDown() 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
long getCount() 返回当前计数。
String toString() 返回标识此锁存器及其状态的字符串。

CyclicBarrier

CyclicBarrier和CountDownLatch不同,CyclicBarrier是当await的数量到达了设定的数量后,才继续往下执行

该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

方法 意义
CyclicBarrier(int parties) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。
int await() 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。

ReentrantLock

一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

方法 意义
ReentrantLock() 创建一个 ReentrantLock 的实例。
void lock() 获取锁。
void unlock() 试图释放此锁。
Condition newCondition() 返回用来与此 Lock 实例一起使用的 Condition 实例。

Condition

条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。

Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

  • void await()

    当前线程在接到信号或被中断之前一直处于等待状态。

  • void signal()

    唤醒一个等待线程。

  • void signalAll()

    唤醒所有等待线程。

ReentrantReadWriteLock

读写锁,此锁最多支持 65535 个递归写入锁和 65535 个读取锁。试图超出这些限制将导致锁方法抛出 Error。

可以方便实现读者–写者问题

方法 意义
ReentrantReadWriteLock.ReadLock readLock() 返回用于读取操作的锁。
ReentrantReadWriteLock.WriteLock writeLock() 返回用于写入操作的锁。

ReentrantReadWriteLock.ReadLock

  • lock()
  • unlock()

ReentrantReadWriteLock.WriteLock

  • lock()
  • unlock()

Exchager

可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。

Exchanger<V>

V - 可以交换的对象类型

方法 意义
Exchanger() 创建一个新的 Exchanger。
V exchange(V x) 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。
V exchange(V x, long timeout, TimeUnit unit) 等待另一个线程到达此交换点(除非当前线程被中断,或者超出了指定的等待时间),然后将给定的对象传送给该线程,同时接收该线程的对象。

总结

  1. 并发框架下的集合类:

    • ArrayBlockingQueue:一个有界阻塞队列,可以实现生产者–消费者问题
    • CopyOnWriteArrayList:ArrayList 的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。
    • CopyOnWriteArraySet:最适合于具有以下特征的应用程序:set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
    • LinkedBlockingQueue:链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。
    • ConcurrentLinkedQueue:基于链接节点的无界线程安全队列
    • ConcurrentHashMap:线程安全的HashMap实现
  2. 工具类
    • CountDownLatch
    • CyclicBarrier

      cyclic:循环的,周期的

    上述两个工具类都可以用来实现一个线程等待多个线程结束,从而确保几乎所有线程同时执行

  3. 原子操作
    • AtomicInteger
    • AtomicBoolean
  4. 获取其他线程的返回值
    • Callable
    • FutureTask
  5. 资源竞争
    • Semphore
  6. 互斥
    • ReentrantLock
    • Condition
    • ReentrantReadWriteLock
    • ReentrantReadWriteLock.WriteLock
    • ReentrantReadWriteLock.ReadLock

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-23 11:21:06

Java并发包总结的相关文章

【java基础】Java并发包

Java并发包 一.并发包的结构 java并发包中共分为五类: 1.集合框架:包括队列和并发集合 2.同步辅助类 3.线程池 4.Lock锁 5.原子类 二.详解部分 1.同步辅助类详解部分 (1)CountDownLatch 举例:有三个工作,只有三个工作都完成,任务才算执行完成. 1 import java.util.concurrent.CountDownLatch; 2 3 /** 4 * 5 * @author qiuxiang 6 * 7 */ 8 public class Coun

Java并发包——Blockingqueue,ConcurrentLinkedQueue,Executors

背景 通过做以下一个小的接口系统gate,了解一下mina和java并发包里的东西.A系统为javaweb项目,B为C语言项目,gate是本篇须要完毕的系统. 需求 1. A为集群系统,并发较高,会批量发送给gate消息,而且接受gate返回的消息. 2. gate独立部署,将从A接受到的消息压入队列,与B建立连接后,将每条消息验证签名等工作后,发送给B.须要保证性能: 3. B负责处理消息,并返回处理结果,B为gate提供提供六个port,一个port可有三个长连接(须由gate发送心跳保持长

Java并发包源码学习之AQS框架(一)概述

AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.concurrent的核心之一,也可以说是阅读整个并发包源码的一个突破口. 比如读ReentrantLock的源码你会发现其核心是它的一个内部类Sync: 整个包中很多类的结构都是如此,比如Semaphore,CountDownLatch都有一个内部类Sync,而所有的Sync都是继承自AbstractQ

java并发包小结(二)

接上一篇 java并发包小结(一):http://blog.csdn.net/aalansehaiyang52/article/details/8877579 Future 接口Future 接口允许表示已经完成的任务.正在执行过程中的任务或者尚未开始执行的任务.通过 Future 接口,可以尝试取消尚未完成的任务,查询任务已经完成还是取消了,以及提取(或等待)任务的结果值.FutureTask 类实现了 Future,并包含一些构造函数,允许将 Runnable 或 Callable(会产生结

java并发包小结(一)

java.util.concurrent 包含许多线程安全.高性能的并发构建块.换句话讲,创建 java.util.concurrent 的目的就是要实现 Collection 框架对数据结构所执行的并发操作.通过提供一组可靠的.高性能并发构建块,开发人员可以提高并发类的线程安全.可伸缩性.性能.可读性和可靠性. JDK 5.0 中的并发改进可以分为三组:    1. JVM 级别更改.大多数现代处理器对并发对某一硬件级别提供支持,通常以 compare-and-swap (CAS)指令形式.C

深入浅出Java并发包—锁机制(三)

接上文<深入浅出Java并发包—锁机制(二)>  由锁衍生的下一个对象是条件变量,这个对象的存在很大程度上是为了解决Object.wait/notify/notifyAll难以使用的问题. 条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”).因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联.等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并

深入浅出Java并发包—锁机制(二)

接上文<深入浅出Java并发包—锁机制(一)  >  2.Sync.FairSync.TryAcquire(公平锁) 我们直接来看代码 protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (isFirst(current) && compareAndSetStat

java并发包研究之-ConcurrentHashMap

概述 HashMap是非线程安全的,HashTable是线程安全的. 那个时候没怎么写Java代码,所以根本就没有听说过ConcurrentHashMap,只知道面试的时候就记住这句话就行了…至于为什么是线程安全的,内部怎么实现的,通通不了解. 今天我们将深入剖析一个比HashTable性能更优的线程安全的Map类,它就是ConcurrentHashMap,本文基于Java 7的源码做剖析. ConcurrentHashMap的目的 多线程环境下,使用Hashmap进行put操作会引起死循环,导

使用Java并发包线程池和XML实现定时任务动态配置和管理

文章标题:使用并发包线程池和XML实现定时任务动态配置和管理 文章地址: http://blog.csdn.net/5iasp/article/details/32705601 作者: javaboy2012Email:[email protected]qq:    1046011462 项目结构: 一.采用的知识点: 1. java并发包2. xml配置文件读取3. 反射动态调用类的方法 二. 基本思路 1.  创建线程池: ScheduledExecutorService scheduExe