实现一个不阻塞的Queue
public class QueueUseLink<E> {
private Node<E> head;
private Node<E> tail;
int capacity;
int size;
public QueueUseLink(int capacity) {
this.capacity = capacity;
}
static class Node<E> {
E value;
Node<E> next;
public Node(E value) {
this.value = value;
}
}
boolean offer(E e) {
final Node<E> newNode = new Node<>(e);
if (size == capacity) {
return false;
}
size++;
if (tail == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
return true;
}
E peek() {
return head.value;
}
E poll() {
if (head == null) {
return null;
} else {
E val = head.value;
head = head.next;
return val;
}
}
public static void main(String[] args) {
final QueueUseLink<String> queue = new QueueUseLink<>(3);
queue.offer("a");
queue.offer("b");
queue.offer("c");
final boolean b = queue.offer("d");
final String peek1 = queue.peek();
final String peek2 = queue.peek();
final String poll1 = queue.poll();
final String poll2 = queue.poll();
final String poll3 = queue.poll();
System.out.println();
}
}
使用wait、notify实现BlockQueue
public class BlockQueueUseWaitNotify<E> {
private Node<E> head;
private Node<E> tail;
int capacity;
int size;
private Object lock = new Object();
public BlockQueueUseWaitNotify(int capacity) {
this.capacity = capacity;
}
static class Node<E> {
E value;
Node<E> next;
public Node(E value) {
this.value = value;
}
}
public void put(E e) throws InterruptedException {
synchronized (lock) {
Node<E> newNode = new Node<>(e);
for (;;) {
if (capacity == size) {
lock.wait();
continue;
}
if (tail == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
size++;
break;
}
}
}
public E take() throws InterruptedException {
synchronized (lock) {
for (;;) {
if (head == null) {
lock.wait();
} else {
E val = head.value;
head = head.next;
size--;
lock.notify();
return val;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
BlockQueueUseWaitNotify<String> blockQueue = new BlockQueueUseWaitNotify<>(3);
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(10);
final String take4 = blockQueue.take();
System.out.println("take4=" + take4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
blockQueue.put("a");
blockQueue.put("b");
blockQueue.put("c");
blockQueue.put("d");
final String take1 = blockQueue.take();
final String take2 = blockQueue.take();
final String take3 = blockQueue.take();
System.out.println();
}
}
使用Condition的signal、await实现BlockQueue
public class BlockQueueUseCondition<E> extends AbstractQueuedSynchronizer {
private Node<E> head;
private Node<E> tail;
int capacity;
int size;
static class Node<E> {
E value;
Node<E> next;
public Node(E value) {
this.value = value;
}
}
ReentrantLock lock = new ReentrantLock();
Condition putCondition = lock.newCondition();
Condition takeCondition = lock.newCondition();
public BlockQueueUseCondition(int capacity) {
this.capacity = capacity;
}
public void put(E e) throws InterruptedException {
Node<E> newNode = new Node<>(e);
lock.lock();
for (;;) {
if (capacity == size) {
putCondition.await();
continue;
}
if (tail == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
size++;
break;
}
takeCondition.signal();
lock.unlock();
}
public E take() throws InterruptedException {
lock.lock();
for (;;) {
if (head == null) {
takeCondition.await();
} else {
E val = head.value;
head = head.next;
size--;
putCondition.signal();
lock.unlock();
return val;
}
}
}
public static void main(String[] args) throws InterruptedException {
BlockQueueUseCondition<String> blockQueue = new BlockQueueUseCondition<>(3);
new Thread(() -> {
try {
final String take = blockQueue.take();
System.out.println("take0:" + take);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(5);
final String take4 = blockQueue.take();
System.out.println("take4=" + take4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
blockQueue.put("a");
blockQueue.put("b");
blockQueue.put("c");
blockQueue.put("d");
blockQueue.put("e");
final String take1 = blockQueue.take();
final String take2 = blockQueue.take();
final String take3 = blockQueue.take();
System.out.println();
}
}