实现阻塞队列(生产者——消费者)

阻塞队列:

  • 取数据,在没有数据的时候处于等待阻塞状态,有数据的时候可以从队列中取出数据。
  • 存数据,队列中存放的数据已满的时候处于等待状态,有空间存数据的时候可以进行存数据。

怎样实现阻塞?

对于阻塞队列需要两个方法:取数据put()方法 和 存数据get()方法。

  1. 使用synchronized()+wait()+notify()来实现阻塞队列。当队列中没有数据,执行get()方法时,会调用wait()方法进行阻塞,只有当执行了put()方法存数据之后,调用notify()方法,才能唤醒get()方法继续执行取数据的操作。当队列中数据已满,执行put()方法时,会调用wait()方法进行阻塞,只有当执行了get()方法取了数据之后,调用notify()方法,才能唤醒put()方法进行执行存数据的操作。
  2. 使用Java5中的ReentrantLock的Condition对象来实现阻塞队列。

具体实现代码:

  • synchronized()+wait()+notify()
package com.learn.BlockingQueue;

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * wait和notify实现阻塞队列(生产者——消费者)
 */
public class WaitAndNofifyQueue {
    public static void main(String[] args) throws InterruptedException {
        OptQueue optQueue = new OptQueue();
        TheQueue theQueue = new TheQueue(3);
        //取元素
        GetThread getThread1 = new GetThread(optQueue,theQueue);
        getThread1.setName("我来取元素了:");
        getThread1.start();
        Thread.sleep(1000);
        //放元素
        PutThread putThread1 = new PutThread(optQueue,theQueue,"A");
        putThread1.setName("我放了元素A:");
        putThread1.start();
        Thread.sleep(1000);
        PutThread putThread2 = new PutThread(optQueue,theQueue,"B");
        putThread2.setName("我放了元素B:");
        putThread2.start();
        Thread.sleep(1000);
        PutThread putThread3 = new PutThread(optQueue,theQueue,"C");
        putThread3.setName("我放了元素C:");
        putThread3.start();
        Thread.sleep(1000);
        PutThread putThread4 = new PutThread(optQueue,theQueue,"D");
        putThread4.setName("我放了元素D:");
        putThread4.start();
        Thread.sleep(1000);
        PutThread putThread5 = new PutThread(optQueue,theQueue,"E");
        putThread5.setName("我放了元素E:");
        putThread5.start();
        //取元素
        GetThread getThread2 = new GetThread(optQueue,theQueue);
        getThread2.setName("我来取元素了:");
        getThread2.start();


    }
}

//操作队列
class OptQueue{
    private final Object lock = new Object();
    private Object ret;
    //取元素。当队列中没有元素,则阻塞
    public void get(TheQueue theQueue){
        synchronized (lock){
            while(theQueue.count.get() == theQueue.minSize){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //取排在首位的元素
            ret = theQueue.list.removeFirst();
            //计数器-1
            theQueue.count.decrementAndGet();
            //此时已经有空间存放元素,可以唤醒另一个 放元素 的线程
            lock.notify();
            System.out.println(Thread.currentThread().getName()+"取走了元素"+ret+"此时队列的大小为"+theQueue.list.size());
        }
    }
    //放元素。当队列中元素满了,则阻塞
    public void put(Object o,TheQueue theQueue){
        synchronized (lock){
            while(theQueue.count.get() == theQueue.maxSize){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //放元素
            theQueue.list.add(o);
            //计数器+1
            theQueue.count.incrementAndGet();
            //此时已经有元素,可以唤醒另一个 取元素 的线程
            lock.notify();
            System.out.println(Thread.currentThread().getName()+"元素"+o+"已放入,此时队列的大小为"+theQueue.list.size());
        }
    }
}

class TheQueue{
    //1.需要一个承装元素的队列
    public LinkedList<Object> list = new LinkedList<>();

    //2.计数器
    public  AtomicInteger count = new AtomicInteger(0);

    //3.队列的上限和下限
    final int maxSize;

    final int minSize = 0;

    //4.构造方法
    public TheQueue(int size){
        this.maxSize = size;
    }
}

//取元素的线程
class GetThread extends Thread{
    OptQueue optQueue;
    TheQueue theQueue;

    public GetThread(OptQueue optQueue,TheQueue theQueue) {
        this.optQueue = optQueue;
        this.theQueue = theQueue;
    }

    @Override
    public void run() {
        super.run();
        optQueue.get(theQueue);
    }
}

//放元素的线程
class PutThread extends Thread{
    OptQueue optQueue;
    TheQueue theQueue;
    Object object;

    public PutThread(OptQueue optQueue,TheQueue theQueue,Object object) {
        this.optQueue = optQueue;
        this.theQueue = theQueue;
        this.object = object;
    }

    @Override
    public void run() {
        super.run();
        optQueue.put(object,theQueue);
    }
}

  • Java5中的ReentrantLock的Condition对象
package com.learn.BlockingQueue;


import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockQueue {
    public static void main(String[] args) throws InterruptedException {
        OptQueueTest optQueue = new OptQueueTest();
        TheQueueTest theQueue = new TheQueueTest(3);
        //取元素
        GetThreadTest getThread1 = new GetThreadTest(optQueue,theQueue);
        getThread1.setName("我来取元素了:");
        getThread1.start();
        Thread.sleep(1000);
        //放元素
        PutThreadTest putThread1 = new PutThreadTest(optQueue,theQueue,"A");
        putThread1.setName("我放了元素AA:");
        putThread1.start();
        Thread.sleep(1000);
        PutThreadTest putThread2 = new PutThreadTest(optQueue,theQueue,"B");
        putThread2.setName("我放了元素BB:");
        putThread2.start();
        Thread.sleep(1000);
        PutThreadTest putThread3 = new PutThreadTest(optQueue,theQueue,"C");
        putThread3.setName("我放了元素CC:");
        putThread3.start();
        Thread.sleep(1000);
        PutThreadTest putThread4 = new PutThreadTest(optQueue,theQueue,"D");
        putThread4.setName("我放了元素DD:");
        putThread4.start();
        Thread.sleep(1000);
        PutThreadTest putThread5 = new PutThreadTest(optQueue,theQueue,"E");
        putThread5.setName("我放了元素EE:");
        putThread5.start();
        //取元素
        GetThreadTest getThread2 = new GetThreadTest(optQueue,theQueue);
        getThread2.setName("我来取元素了:");
        getThread2.start();


    }
}

//操作队列
class OptQueueTest{
    //声明锁
    private ReentrantLock lock = new ReentrantLock();
    //队列没有满的条件
    private Condition notFull = lock.newCondition();
    //队列不空的条件
    private Condition notEmpty = lock.newCondition();
    private Object ret;
    //取元素。当队列中没有元素,则阻塞
    public void get(TheQueueTest theQueue){
        lock.lock();
        try {
            while(theQueue.count.get() == theQueue.minSize){
                notEmpty.await();
            }
            //取排在首位的元素
            ret = theQueue.list.removeFirst();
            //计数器-1
            theQueue.count.decrementAndGet();
            //此时已经有空间存放元素,可以唤醒另一个 放元素 的线程
            notFull.signal();
            System.out.println(Thread.currentThread().getName()+"取走了元素"+ret+"此时队列的大小为"+theQueue.list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }
    //放元素。当队列中元素满了,则阻塞
    public void put(Object o,TheQueueTest theQueue){
        lock.lock();
        try {
            while(theQueue.count.get() == theQueue.maxSize){
                notFull.await();
            }
            //放元素
            theQueue.list.add(o);
            //计数器+1
            theQueue.count.incrementAndGet();
            //此时已经有元素,可以唤醒另一个 取元素 的线程
            notEmpty.signal();
            System.out.println(Thread.currentThread().getName()+"元素"+o+"已放入,此时队列的大小为"+theQueue.list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }
}

class TheQueueTest{
    //1.需要一个承装元素的队列
    public LinkedList<Object> list = new LinkedList<>();

    //2.计数器
    public AtomicInteger count = new AtomicInteger(0);

    //3.队列的上限和下限
    final int maxSize;

    final int minSize = 0;

    //4.构造方法
    public TheQueueTest(int size){
        this.maxSize = size;
    }
}

//取元素的线程
class GetThreadTest extends Thread{
    OptQueueTest optQueue;
    TheQueueTest theQueue;

    public GetThreadTest(OptQueueTest optQueue,TheQueueTest theQueue) {
        this.optQueue = optQueue;
        this.theQueue = theQueue;
    }

    @Override
    public void run() {
        super.run();
        optQueue.get(theQueue);
    }
}

//放元素的线程
class PutThreadTest extends Thread{
    OptQueueTest optQueue;
    TheQueueTest theQueue;
    Object object;

    public PutThreadTest(OptQueueTest optQueue,TheQueueTest theQueue,Object object) {
        this.optQueue = optQueue;
        this.theQueue = theQueue;
        this.object = object;
    }

    @Override
    public void run() {
        super.run();
        optQueue.put(object,theQueue);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值