今天用ArrayBlockingQueue写了一个简单的消费者和生产者模型,代码如下
public class Client {
private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10,true);
public static void main(String[] args) throws Exception {
Client client = new Client();
Producer producer = client.new Producer();
Consumer consumer = client.new Consumer();
producer.start();
consumer.start();
}
class Producer extends Thread{
@Override
public void run() {
super.run();
for (int i = 0; i < 100; i++) {
try {
queue.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("producer:"+i);
}
}
}
class Consumer extends Thread{
@Override
public void run() {
super.run();
for (int i = 0; i < 100; i++) {
int t = queue.poll();
System.out.println("consumer:"+t);
}
}
}
}
运行时结果却不是我们想要的,消费者输出了很多的null,将poll()方法改为take()方法后,实现了正确输出,那这两个方法有什么区别呢?看看源码
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
从源码中可以看出,当队列为null的时候,poll()方法会直接返回null, 不会抛出异常,但是take()方法会一直等待,因此会抛出一个InterruptedException类型的异常。因此我们实现生产者消费者的时候只能用take()方法。