1.synchronized实现
队列
static class MyBlockingQueue<E> {
private Queue<E> queue = null;
private int limit;
public MyBlockingQueue(int limit) {
this.limit = limit;
queue = new ArrayDeque<>(limit);
}
public synchronized void put(E e) throws InterruptedException {
while (queue.size() == limit) {
wait();
}
queue.add(e);
notifyAll();
}
public synchronized E take() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
E e = queue.poll();
notifyAll();
return e;
}
}
生产者:
static class Producer extends Thread {
MyBlockingQueue<String> queue;
public Producer(MyBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
int num = 0;
try {
while (true) {
String task = String.valueOf(num);
queue.put(task);
System.out.println("produce task " + task);
num++;
Thread.sleep((int) (Math.random() * 100));
}
} catch (InterruptedException e) {
}
}
}
消费者:
static class Consumer extends Thread {
MyBlockingQueue<String> queue;
public Consumer(MyBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
String task = queue.take();
System.out.println("handle task " + task);
Thread.sleep((int)(Math.random()*100));
}
} catch (InterruptedException e) {
}
}
}
main:
public static void main(String[] args) {
MyBlockingQueue<String> queue = new MyBlockingQueue<>(10);
new Producer(queue).start();
new Consumer(queue).start();
}
2.显示锁实现
队列
static class MyBlockingQueue<E> {
private Queue<E> queue = null;
private int limit;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public MyBlockingQueue(int limit) {
this.limit = limit;
queue = new ArrayDeque<>(limit);
}
public void put(E e) throws InterruptedException {
lock.lockInterruptibly();
try{
while (queue.size() == limit) {
notFull.await();
}
queue.add(e);
notEmpty.signal();
}finally{
lock.unlock();
}
}
public E take() throws InterruptedException {
lock.lockInterruptibly();
try{
while (queue.isEmpty()) {
notEmpty.await();
}
E e = queue.poll();
notFull.signal();
return e;
}finally{
lock.unlock();
}
}
}
3.线程池
直接将任务丢给线程池,需要结果的话就get即可
生产者把任务丢给线程池,线程池创建线程并处理任务;
如果需要运行的任务数大于线程池的核心线程数,就把任务扔到阻塞队列里。
这种做法比只使用一个阻塞队列来实现生产者和消费者模式显然要高明很多,因为消费者能够处理直接就处理掉了(execute方法里就有“创建线程并执行”的步骤),这样速度更快,而生产者先存,消费者再取这种方式显然慢一些。