看了下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
说明:在Producer和Consumer线程里面打印语句的显示结果很令人迷惑,改成在BlockQueue里面打印就好了。