使用notiy和wait模拟阻塞队列

public class MyQueue {

    //定义一个存储数据的容器
    private LinkedList<Object> list = new LinkedList<Object>();

    //定义容器的最小容量
    private int minSize = 0;

    //定义容器的最大容量
    private int maxSize;

    //定义队列的长度
    private AtomicInteger size = new AtomicInteger(0);

    //定义一个锁对象
    private Object lock = new Object();

    public MyQueue(int maxSize){
        this.maxSize = maxSize;
    }

    //put方法,向队列中假数据,如果队列满则阻塞直到有空闲的空间
    public void put(Object obj){
        synchronized (lock) {
            while(maxSize == size.get()){
                try {
                    //1.如果队列满,则阻塞
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //2.如果有空间了,首先添加一个元素
            list.add(obj);
            //3.当前的size加1
            size.incrementAndGet();
            System.out.println("存入元素"+obj);
            //4.唤醒所有的take等待线程
            lock.notify();
        }
    }

    //take方法,从队列中取数据,如果队列为空,那么阻塞直到有一个可用元素为止
    public Object take(){
        Object ret = null;
        synchronized (lock) {
            while(minSize == size.get()){
                try {
                    //1.如果队列中没有元素,则等待
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //2.如果队列中有值了,取出值
            ret = list.removeFirst();
            //3.队列的长度减1
            size.decrementAndGet();
            //4.唤醒所有的put等待线程
            lock.notify();
            System.out.println("取出元素"+ret);
        }
        return ret;
    }

    //得到当前的长度
    public int getSize(){
        return size.get();
    }

    public static void main(String[] args) throws InterruptedException {

        final MyQueue myQueue = new MyQueue(5);
        myQueue.put("1");
        myQueue.put("2");
        myQueue.put("3");
        myQueue.put("4");
        myQueue.put("5");

        System.out.println("myQueue的长度是:"+myQueue.getSize());

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                myQueue.put("6");
                myQueue.put("7");
            }
        },"t1");

        t1.start();

        TimeUnit.SECONDS.sleep(5);

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                myQueue.take();
                myQueue.take();
            }
        },"t1");
        t2.start();
    }

}

执行结果:

存入元素1
存入元素2
存入元素3
存入元素4
存入元素5
myQueue的长度是:5
取出元素1
取出元素2
存入元素6
存入元素7
时间: 2024-10-13 02:16:30

使用notiy和wait模拟阻塞队列的相关文章

wait/notify模拟阻塞队列

程序代码如下: public class MyQueue<E> {     //1. 提供集合容器     private List<E> list = new ArrayList<E>();     //2. 提供计数器     private AtomicInteger counter = new AtomicInteger();     //3. 提供 上限 下限     private int MAX;     private int MIN = 0;     

Java-SynchronousQueue 阻塞队列小记

在BlockingQueue的子类中有一个SynchronousQueue(同步队列)比较少见,现在做一个简单的介绍,并附加一个简单的例子. SynchronousQueue --JDK1.6介绍: public class SynchronousQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable 一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然

并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法(转)

在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出).Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列. 注:什么叫线程安全?这个首先要明确.线程安全就是说多线程访问同一代码,不会产生不确定的结果. 并行和并发区别 1.并行是指两者同时执行一件事,比如赛跑,两个人都在不停的

线程队列之阻塞队列LinkedBlockingQueue

在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出).Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列. 注:什么叫线程安全?这个首先要明确.线程安全就是说多线程访问同一代码,不会产生不确定的结果. 并行和并发区别 1.并行是指两者同时执行一件事,比如赛跑,两个人都在不停的

阻塞队列和并发队列

在并发编程中我们有时候需要使用线程安全的队列.要实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法. 使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,其中阻塞队列的典型是:BlockingQueue; 非阻塞的实现方式则可以使用循环CAS的方式来实现,非阻塞队列的典型例子是ConcurrentLinkedQueue. 注:并行与并发的区别: 1.并行是指两者同时执行一件事,比如赛跑,两个人都在不停的往前跑: 2.并

用阻塞队列和线程池简单实现生产者和消费者场景

本例子仅仅是博主学习阻塞队列和后的一些小实践,并不是真正的应用场景! 生产者消费者场景是我们应用中最常见的场景,我们可以通过ReentrantLock的Condition和对线程进行wait,notify同通信来实现生产者和消费者场景,前者可以实现多生产者和多消费者模式,后者仅可以实现一生产者,一消费者模式. 今天我们就利用阻塞队列来实现下生产者和消费者模式(里面还利用了线程池). 看过我关于阻塞队列博文的朋友已经知道,阻塞队列其实就是由ReentrantLock实现的! 场景就不描述了,为简单

JAVA并发之阻塞队列浅析

背景 因为在工作中经常会用到阻塞队列,有的时候还要根据业务场景获取重写阻塞队列中的方法,所以学习一下阻塞队列的实现原理还是很有必要的.(PS:不深入了解的话,很容易使用出错,造成没有技术深度的样子) 阻塞队列是什么? 要想了解阻塞队列,先了解一下队列是啥,简单的说队列就是一种先进先出的数据结构.(具体的内容去数据结构里学习一下)所以阻塞队列就是一种可阻塞的队列.和普通的队列的不同就体现在 ”阻塞“两个字上.阻塞是啥意思? 百度看一下 在软件工程里阻塞一般指的是阻塞调用,即调用结果返回之前,当前线

Callable,阻塞队列,线程池问题

一.说说Java创建多线程的方法 1. 通过继承Thread类实现run方法   2. 通过实现Runnable接口 3. 通过实现Callable接口 4. 通过线程池获取 二. 可以写一个Callable的案例吗?如何调用Callable接口 /*是一个带返回值的多线程类,如果需要有线程返回的结果,就需要使用此类*/ class MyThread implements Callable<Integer> { @Override public Integer call() { return

常用阻塞队列 BlockingQueue 有哪些?

为什么要使用阻塞队列 之前,介绍了一下 ThreadPoolExecutor 的各参数的含义(并发编程之线程池ThreadPoolExecutor),其中有一个 BlockingQueue,它是一个阻塞队列.那么,小伙伴们有没有想过,为什么此处的线程池要用阻塞队列呢? 我们知道队列是先进先出的.当放入一个元素的时候,会放在队列的末尾,取出元素的时候,会从队头取.那么,当队列为空或者队列满的时候怎么办呢. 这时,阻塞队列,会自动帮我们处理这种情况. 当阻塞队列为空的时候,从队列中取元素的操作就会被