线程并发学习
线程并发学习—-核心概念(转载)
线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify、join)
线程并发学习—-线程阻塞(synchronized)
线程并发学习—-线程阻塞(lock)
线程并发学习—-Thread、Runnable、Callable
线程并发学习—-队列(Queue)
spring学习—-线程池
java中一些锁概念整理(转载)
Queue类图
Queue简介
public interface Queue<E> extends Collection<E> {
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}
public interface BlockingQueue<E> extends Queue<E> {
//入队元素,队列满了会抛出异常 底层调用offer实现
boolean add(E e);
//入队元素 队列满了直接返回false
boolean offer(E e);
//入队元素 队列满了 则等待
void put(E e) throws InterruptedException;
boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException;
//出队
E take() throws InterruptedException;
//出队
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
int remainingCapacity();
boolean remove(Object o);
public boolean contains(Object o);
}
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
implements Queue<E> {
protected AbstractQueue() {
}
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
....
从上面的源码码可以看出
添加方法:
add(E e); //入队元素,队列满了会抛出异常 底层调用offer实现
offer(E e); //入队元素 队列满了直接返回false
put(E e); //入队元素 队列满了 则等待
获取方法
element 底层调用peek实现
peek 队列为空时,返回null
移除方法
remove 移除元素 没有元素抛出异常 底层调用poll
poll 移除元素 没有返回null
take 移除元素 没有则等待
常用队列
ArrayBlockingQueue
简介
- ArrayBlockingQueue是一个阻塞队列,底层使用数组结构实现,按照先进先出(FIFO)的原则对元素进行排序
- ArrayBlockingQueue是一个线程安全的集合,使用ReentrantLock的非公平锁,保证线程安全,在并发情况下可以保证数据的一致性
- ArrayBlockingQueue大小是有限的,大小在初始化的时候就确定了,不会自动扩容,是一个“有界缓存区”
部分源码
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
//入队底层实现,定义为私有方法
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
//出队底层实现,定义为私有方法
private E dequeue() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
}
LinkedBlockingQueue
简介
- LinkedBlockingQueue是一个阻塞队列,底层使用链表结构实现,实现先进先出(FIFO)的原则
- LinkedBlockingQueue是一个线程安全的集合,使用ReentrantLock的非公平锁,保证线程安全,在并发情况下可以保证数据的一致性(有两把锁,一把读锁,一把写锁)
LinkedBlockingQueue一般认为是无限的,默认大小为int的最大值2147483647
入队: 首先,将最后的结点指向新插入的结点,其次将last结点置为新插入的结点,流程结束!
出队: 头部元素永远为null
部分源码
//LinkedBlockingQueue 可以实现了两把锁,可以同时读写,在同时出队入队时,都会涉及到对元素数量的并发修改,会有线程安全的问题,故计数使用原子类,底层使用CAS解决数据安全问题
private final AtomicInteger count = new AtomicInteger();
static class Node<E> {
E item;
Node<E> next;
Node(E x) { item = x; }
}
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
//入队
private void enqueue(Node<E> node) {
last = last.next = node;
}
//出队
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
ArrayBlockingQueue与LinkedBlockingQueue比较
- ArrayBlockingQueue使用数组实现,有界,必须指定数组大小;LinkedBlockingQueue使用链表实现,默认为无界(最大2147483647)
- ArrayBlockingQueue和LinkedBlockingQueue都使用ReetrantLock
- ArrayBlockingQueue只有一把锁,只能入队或出队一个在执行;LinkedBlockingQueue有两把锁,可以做到同一时刻既消费、又生产。多个CPU的时候LinkedBlockingQueue性能要更好一点
参考资料
http://mp.weixin.qq.com/s/Ft2y0yBSzF-mUSK8Iwhemw
http://mp.weixin.qq.com/s/0yfjpbZBcTN7ntZJnyJ-Sg
http://mp.weixin.qq.com/s/3yXZXwRKMOBMo8G6WpOmyw