1,LinkedListDeque:双端队列、加入了游标遍历模式,顺序迭代的效率能够约等于数组遍历的效率;
2,ConcurrentLinkedListDeque:线程安全的双端队列,使用SerialConvertor线程串行方法,将同时访问的多个线程串行化,并依据进入次序,依次执行;
import java.util.concurrent.ConcurrentHashMap;
/**
* 双端链表队列
* @author huwei
*/
public class LinkedListDeque {
/**
* 队列容量
* 指定队列容纳数据的边界,超出容量不能存入
* 默认为Integer.MAX_VALUE
*/
private int capacity;
/**
* 当前数据数量
*/
private int size;
final private Node DEFAULT_TAIL = new Node();
final private Node DEFAULT_HEAD = new Node();
/**
* 尾
*/
private Node tail;
/**
* 头
*/
private Node head;
private ConcurrentHashMap<Thread, Cursor> cursors = new ConcurrentHashMap<Thread, LinkedListDeque.Cursor>();
public LinkedListDeque() {
this(Integer.MAX_VALUE);
}
public LinkedListDeque(int capacity) {
this.capacity = capacity;
initHeadAndTail();
}
private void initHeadAndTail() {
tail = DEFAULT_TAIL;
head = DEFAULT_HEAD;
size = 0;
relateNode(head ,tail);
}
public int capacity() {
return capacity;
}
public Node addFirst(Object val) {
return addNode(head, val, head.getNext());
}
public Node addLast(Object val) {
return addNode(tail.getPrev(), val, tail);
}
private Node addNode(Node prev ,Object val ,Node next) {
checkBound();
Node node = createNode(val);
relateNode(prev ,node);
relateNode(node ,next);
incrSize();
return node;
}
public Node insertBefore(int index ,Object val) {
Node node = findNode(index);
return addNode(node.getPrev(), val, node);
}
public Node insertAfter(int index ,Object val) {
return insertBefore(++index, val);
}
public Node insertBefore(Node node ,Object val) {
checkNull(node);
if(!containsNode(node)) {
throw new RuntimeException("node is not exists!!");
}
return addNode(node.getPrev(), val, node);
}
private boolean containsNode(Node node) {
Node temp = node;
while(temp.getPrev() != null) {
temp = temp.getPrev();
}
return temp == head;
}
public Node insertAfter(Node node,Object val) {
return insertBefore(node == null ? null : node.getNext(), val);
}
private void checkNull(Object obj) {
if(null == obj) {
throw new RuntimeException("obj is null");
}
}
private Node findNode(int index) {
checkBound();
checkCursor(index);
return cursor0(index).node;
}
private void checkCursor(int index) {
if(index >= size || index < 0) {
throw new RuntimeException("index out bound size =" + size +" ,index = " +index);
}
}
public Node pollFirst() {
return releaseNode(getFirst());
}
public Node pollLast() {
return releaseNode(getLast());
}
public Node getFirst() {
return head.getNext() == tail ? null : head.getNext();
}
public Node getLast() {
return tail.getPrev() == head ? null : tail.getPrev();
}
/**
* 建议使用游标
* @param index
* @return
*/
public Node get(int index) {
return findNode(index);
}
/**
* 使用游标的方式遍历节点
* @param index 游标
* @return
*/
public Node cursor(int index) {
checkCursor(index);
Node result = null;
Thread current = Thread.currentThread();
Cursor cursor = cursors.get(current);
if(cursor == null){
cursor = cursor0(index);
}else {
cursor = cursor0(index ,cursor.cursor ,cursor.node);
}
result = cursor.node;
if(cursor.node.getNext() == tail) {
System.out.println("删除游标");
removeCursor();
}
else {
cursors.put(current, cursor);
}
return result;
}
private Node findNext(int count ,Node head) {
Node temp = head;
int tCount = 0;
while(temp.getNext() != null) {
if(count == tCount ++) {
return temp;
}
temp = temp.getNext();
}
return null;
}
private Node findPrev(int count ,Node tail) {
Node temp = tail;
int tCount = 0;
while(temp.getPrev() != null) {
if(count == tCount ++) {
return temp;
}
temp = temp.getPrev();
}
return null;
}
public void removeCursor() {
cursors.remove(Thread.currentThread());
}
private Cursor cursor0(int index) {
Node node = null;
if(index > size / 2) {
node = findPrev(size - index, tail);
}
else {
node = findNext(index, head.getNext());
}
return new Cursor(index ,node);
}
private Cursor cursor0(int index ,int cursor ,Node node) {
Node result = null;
if(index > cursor) {
if(size - index > index - cursor) {
result = findNext(index - cursor, node);
}
else {
result = findPrev(size - index, tail);
}
}
else if(cursor - index > index) {
result = findNext(index, head.getNext());
}
else {
result = findPrev(cursor - index, node);
}
return new Cursor(index, result);
}
public int contains(Object val) {
Node temp = head.getNext();
int index = -1;
while(temp.getNext() != null && ++index < size) {
if(temp.getData() == val || (val != null && val.equals(temp.getData()))) {
return index;
}
temp = temp.getNext();
}
return -1;
}
private Node findFisrt(Object val) {
Node temp = head.getNext();
while(temp.getNext()!= null) {
if(temp.getData() == val || (val != null && val.equals(temp.getData()))) {
return temp;
}
temp = temp.getNext();
}
return null;
}
private Node findLast(Object val) {
Node temp = tail.getPrev();
while(temp.getPrev() != null) {
if(temp.getData() == val || (val != null && val.equals(temp.getData()))) {
return temp;
}
temp = temp.getPrev();
}
return null;
}
public void remove(Object val) {
removeFirst(val);
}
public void removeFirst(Object val) {
releaseNode(findFisrt(val));
}
private Node releaseNode(Node node) {
if(node != null) {
relateNode(node.getPrev(), node.getNext());
decrSize();
}
return node;
}
public void removeLast(Object val) {
Node node = findLast(val);
releaseNode(node);
}
public void removeAll(Object val) {
Node temp = tail.getPrev();
while(temp.getPrev() != null) {
if(temp.getData() == val || (val != null && val.equals(temp.getData()))) {
releaseNode(temp);
}
temp = temp.getPrev();
}
}
public void clear() {
initHeadAndTail();
}
public int size() {
return size;
}
public boolean empty() {
return size == 0;
}
private void checkBound() {
if(size == capacity) {
throw new RuntimeException(LinkedListDeque.class.getName() +" add ele out bound ,current size="+size+";capacity="+capacity);
}
}
private synchronized void incrSize() {
++size;
}
private synchronized void decrSize() {
--size;
}
private Node createNode(Object val) {
return new Node(val,null,null);
}
private void relateNode(Node prev, Node next) {
prev.setNext(next);
next.setPrev(prev);
}
/**
* 游标
* 用于使用下标访问的快速迭代方式
* @author huwei
*/
private class Cursor {
int cursor;
Node node;
public Cursor(int index, Node node2) {
cursor = index;
node = node2;
}
}
}
/**
* 线程安全的链表双端队列
* @author huwei
*
*/
public class ConcurrentLinkedListDeque {
private LinkedListDeque container;
private SerialConvertor serialConvertor = new SerialConvertor();
public ConcurrentLinkedListDeque() {
this(Integer.MAX_VALUE);
}
public ConcurrentLinkedListDeque(int capacity) {
container = new LinkedListDeque(capacity);
}
public int capacity() {
return container.capacity();
}
public boolean empty() {
return container.empty();
}
public Node addFirst(Object val) {
serialConvertor.addTask();
Node temp = container.addFirst(val);
serialConvertor.pollTask();
return temp;
}
public Node addLast(Object val) {
serialConvertor.addTask();
Node temp = container.addLast(val);
serialConvertor.pollTask();
return temp;
}
public Node insertBefore(int index ,Object val) {
serialConvertor.addTask();
Node temp = container.insertBefore(index, val);
serialConvertor.pollTask();
return temp;
}
public Node insertAfter(int index ,Object val) {
serialConvertor.addTask();
Node temp = container.insertAfter(index, val);
serialConvertor.pollTask();
return temp;
}
public Node insertBefore(Node node ,Object val) {
serialConvertor.addTask();
Node temp = container.insertBefore(node, val);
serialConvertor.pollTask();
return temp;
}
public Node insertAfter(Node node,Object val) {
serialConvertor.addTask();
Node temp = container.insertAfter(node, val);
serialConvertor.pollTask();
return temp;
}
public Node pollFirst() {
serialConvertor.addTask();
Node temp = container.pollFirst();
serialConvertor.pollTask();
return temp;
}
public Node pollLast() {
serialConvertor.addTask();
Node temp = container.pollLast();
serialConvertor.pollTask();
return temp;
}
public Node getFirst() {
return container.getFirst();
}
public Node getLast() {
return container.getLast();
}
public Node get(int index) {
return container.get(index);
}
public Node cursor(int index) {
return container.cursor(index);
}
public void removeCursor() {
container.removeCursor();
}
public int contains(Object val) {
return container.contains(val);
}
public void remove(Object val) {
removeFirst(val);
}
public void removeFirst(Object val) {
serialConvertor.addTask();
container.removeFirst(val);
serialConvertor.pollTask();
}
public void removeLast(Object val) {
serialConvertor.addTask();
container.removeLast(val);
serialConvertor.pollTask();
}
public void removeAll(Object val) {
serialConvertor.addTask();
container.removeAll(val);
serialConvertor.pollTask();
}
public void clear() {
serialConvertor.addTask();
container.clear();
serialConvertor.pollTask();
}
public int size() {
return container.size();
}
private class SerialConvertor {
private LinkedListDeque task = new LinkedListDeque(10000);
volatile private Thread before = null;
void addTask() {
SerialState ss = new SerialState(Thread.currentThread());
synchronized (this) {
if(before == null || before == ss.thread) {
before = ss.thread;
return;
}
addState(ss);
}
synchronized (ss.thread) {
ss.waiting = true;
try {
ss.thread.wait();
} catch (Exception e) {
//线程被中断
removeState(ss);
}
}
}
void pollTask() {
SerialState ss = null;
while((ss = pollTaskAndChangeBefore()) != null) {
if(!ss.waiting) {
addState(ss);
Thread.yield();
continue;
}
synchronized (ss.thread) {
ss.thread.notifyAll();
break;
}
}
}
synchronized SerialState pollTaskAndChangeBefore() {
SerialState ss = pollState();
before = ss == null ? null : ss.thread;
return ss;
}
synchronized void addState(SerialState state) {
task.addLast(state);
}
synchronized SerialState pollState() {
Node node = task.pollFirst();
return node == null ? null : (SerialState)node.getData();
}
synchronized void removeState(SerialState state) {
task.remove(state);
}
class SerialState {
volatile Thread thread;
volatile boolean waiting = false;
public SerialState(Thread t) {
thread = t;
}
}
}
}
public class Node {
// 真实数据
private Object data;
/**
* 上一个节点
*/
private Node prev;
/**
* 下一个节点
*/
private Node next;
/**
* @return the data
*/
public Object getData() {
return data;
}
/**
* @param data the data to set
*/
public void setData(Object data) {
this.data = data;
}
/**
* @return the prev
*/
public Node getPrev() {
return prev;
}
/**
* @param prev the prev to set
*/
public void setPrev(Node prev) {
this.prev = prev;
}
/**
* @return the next
*/
public Node getNext() {
return next;
}
/**
* @param next the next to set
*/
public void setNext(Node next) {
this.next = next;
}
public Node(Object data, Node prev, Node next) {
this.data = data;
this.prev = prev;
this.next = next;
}
public Node() {
}
}