看了下JDK的源代码实现,模拟了一下ArrayBlockQueue,代码如下:
import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class BlockQueue { private List<Integer> list; private int size; private final ReentrantLock lock; private final Condition isEmpty; private final Condition isFull; public BlockQueue(int size) { this.size = size; list = new LinkedList<Integer>(); lock = new ReentrantLock(); isEmpty = lock.newCondition(); isFull = lock.newCondition(); } public void put(int data) throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (list.size() == size) { try { isFull.await(); } catch (InterruptedException e) { isFull.signal(); throw e; } } list.add(data); System.out.println("size : " + list.size() + ", " + Thread.currentThread().getName() + " put " + data); isEmpty.signal(); } finally { lock.unlock(); } } public int take() throws InterruptedException { lock.lockInterruptibly(); try { while (list.size() == 0) { try { isEmpty.await(); } catch (InterruptedException e) { isEmpty.signal(); throw e; } } int data = list.remove(0); System.out.println("size : " + list.size() + ", " + Thread.currentThread().getName() + " get " + data); isFull.signal(); return data; } finally { lock.unlock(); } } }
import java.util.Random; public class Producer implements Runnable { private BlockQueue bq; private String name; public Producer(String name, BlockQueue bq) { this.name = name; this.bq = bq; } @Override public void run() { Random ran = new Random(); for(int i = 0; i < 10; i++){ int data = ran.nextInt(20); try { bq.put(data); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //System.out.println(name + " put " + data); } } }
public class Consumer implements Runnable { private BlockQueue bq; private String name; public Consumer(String name, BlockQueue bq) { this.bq = bq; this.name = name; } @Override public void run() { for(int i = 0; i < 10; i++){ int data; try { data = bq.take(); //System.out.println(name + " get " + data); } catch (InterruptedException e) { e.printStackTrace(); } } } }
import org.junit.Test; public class BlockQueueTest { @Test public void test() throws InterruptedException { BlockQueue bq = new BlockQueue(5); Producer p1 = new Producer("producer 1", bq); Producer p2 = new Producer("producer 2", bq); Producer p3 = new Producer("producer 3", bq); Consumer c1 = new Consumer("consumer 1", bq); Consumer c2 = new Consumer("consumer 2", bq); Consumer c3 = new Consumer("consumer 3", bq); new Thread(p1).start(); new Thread(p2).start(); new Thread(p3).start(); new Thread(c1).start(); new Thread(c2).start(); new Thread(c3).start(); Thread.sleep(10000); } }
size : 1, Thread-0 put 15 size : 2, Thread-0 put 0 size : 3, Thread-0 put 18 size : 4, Thread-0 put 9 size : 5, Thread-0 put 6 size : 4, Thread-3 get 15 size : 3, Thread-5 get 0 size : 2, Thread-5 get 18 size : 1, Thread-5 get 9 size : 0, Thread-5 get 6 size : 1, Thread-1 put 12 size : 0, Thread-4 get 12 size : 1, Thread-0 put 3 size : 2, Thread-2 put 2 size : 3, Thread-2 put 13 size : 4, Thread-2 put 12 size : 5, Thread-2 put 14 size : 4, Thread-5 get 3 size : 3, Thread-5 get 2 size : 2, Thread-5 get 13 size : 1, Thread-5 get 12 size : 0, Thread-5 get 14 size : 1, Thread-1 put 0 size : 2, Thread-1 put 3 size : 3, Thread-1 put 19 size : 4, Thread-1 put 13 size : 5, Thread-1 put 2 size : 4, Thread-4 get 0 size : 3, Thread-4 get 3 size : 2, Thread-4 get 19 size : 1, Thread-4 get 13 size : 0, Thread-4 get 2 size : 1, Thread-2 put 1 size : 2, Thread-2 put 9 size : 3, Thread-2 put 10 size : 4, Thread-2 put 14 size : 5, Thread-2 put 3 size : 4, Thread-5 get 1 size : 3, Thread-3 get 9 size : 2, Thread-3 get 10 size : 1, Thread-3 get 14 size : 0, Thread-3 get 3 size : 1, Thread-1 put 17 size : 2, Thread-1 put 14 size : 3, Thread-1 put 1 size : 4, Thread-1 put 10 size : 3, Thread-4 get 17 size : 2, Thread-4 get 14 size : 1, Thread-4 get 1 size : 0, Thread-4 get 10 size : 1, Thread-2 put 6 size : 2, Thread-0 put 1 size : 3, Thread-0 put 14 size : 4, Thread-0 put 9 size : 5, Thread-0 put 4 size : 4, Thread-3 get 6 size : 3, Thread-3 get 1 size : 2, Thread-3 get 14 size : 1, Thread-3 get 9 size : 0, Thread-3 get 4