J.U.C 中的阻塞队列
在 Java8 中,提供了 7 个阻塞队列
ArrayBlockingQueue | 数组实现的有界阻塞队列, 此队列按照先进先出(FIFO)的原则对元素进行排序。 |
LinkedBlockingQueue | 链表实现的有界阻塞队列, 此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序 |
PriorityBlockingQueue | 支持优先级排序的无界阻塞队列, 默认状况下元素采起天然顺序升序排列。也能够自定义类实现 compareTo()方法来指定元素排序规则,或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来对元素进行排序。 |
DelayQueue | 优先级队列实现的无界阻塞队列 |
SynchronousQueue | 不存储元素的阻塞队列, 每个 put 操做必须等待一个 take 操做,不然不能继续添加元素。 |
LinkedTransferQueue | 链表实现的无界阻塞队列 |
LinkedBlockingDeque | 链表实现的双向阻塞队列 |
阻塞队列的操做方法
在阻塞队列中,提供了四种处理方式数组
- 插入操做
add(e) :添加元素到队列中,若是队列满了,继续插入元素会报错,IllegalStateException。 offer(e) : 添加元素到队列,同时会返回元素是否插入成功的状态,若是成功则返回 true put(e) :当阻塞队列满了之后,生产者继续经过 put添加元素,队列会一直阻塞生产者线程,知道队列可用 offer(e,time,unit) :当阻塞队列满了之后继续添加元素,生产者线程会被阻塞指定时间,若是超时,则线程直接退出 - 移除操做 remove():当队列为空时,调用 remove 会返回 false,若是元素移除成功,则返回 true poll(): 当队列中存在元素,则从队列中取出一个元素,若是队列为空,则直接返回 null take():基于阻塞的方式获取队列中的元素,若是队列为空,则 take 方法会一直阻塞,直到队列中有新的数据,put 操做将会唤醒 take 线程能够消费 poll(time,unit):带超时机制的获取数据,若是队列为空,则会等待指定的时间再去获取元素返回
J.U.C 中的原子操做类
因为变量类型的关系,在 J.U.C 中提供了 12 个原子操做的类。这 12 个类能够分为四大类多线程
- 原子更新基本类型
AtomicBoolean、AtomicInteger、AtomicLong - 原子更新数组
AtomicIntegerArray 、 AtomicLongArray 、AtomicReferenceArray - 原子更新引用 AtomicReference 、 AtomicReferenceFieldUpdater 、AtomicMarkableReference(更新带有标记位的引用类型)
- 原子更新字段 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReferenceAtomicInteger 原理分析
AtomicInteger
getAndIncrement
getAndIncrement 其实是调用 unsafe 这个类里面提供的方法,Unsafe 类咱们前面在分析 AQS 的时候讲过,这个类至关因而一个后门,使得 Java 能够像 C 语言的指针同样直接操做内存空间。固然也会带来一些弊端,就是指针的问题。实际上这个类在不少方面都有使用,除了 J.U.C 这个包之外,还有 Netty、kafka 等等这个类提供了不少功能,包括多线程同步(monitorEnter)、CAS 操 做 (compareAndSwap) 、线程的挂起和恢复(park/unpark)、内存屏障(loadFence/storeFence)内存管理(内存分配、释放内存、获取内存地址等.)this
public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); }
valueOffset
经过 unsafe.objectFieldOffset(),获取当前 Value 这个变量在内存中的偏移量,后续会基于这个偏移量从内存中获得value的值来和当前的值作比较,实现乐观锁线程
private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } }
getAndAddInt 经过 do/while 循环,基于 CAS 乐观锁来作原子递增。实际上前面的 valueOffset 的做用就是从主内存中得到当前value 的值和预期值作一个比较,若是相等,对 value 作递增并结束循环指针
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; }
get 方法
get 方法只须要直接返回 value 的值就行,这里的 value 是经过 Volatile 修饰的,用来保证可见性code