阻塞队列——BlockingQueue

本文介绍阻塞队列的基本概念及其与普通队列的主要区别,并通过两种不同的实现方式来展示阻塞队列的工作机制:一种是使用wait和notifyAll方法,另一种是利用ReentrantLock和Condition条件变量。

阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列。

wait、notifyAll实现方式
package blocks;

import java.util.ArrayList;

/**
 * Created by maxi on 2017/11/8.
 */
public class ObjectBlockQueues<E> implements BlockQueues<E> {
    private final ArrayList<E> lists;
    private int limite;
//    private ReentrantLock mLocks;

    public ObjectBlockQueues() {
        this(10, false);
    }

    public ObjectBlockQueues(int limite) {
        this(limite, false);
    }

    public ObjectBlockQueues(int limite, Boolean isFair) {
        this.limite = limite;
        lists = new ArrayList<E>(limite);
//        mLocks = new ReentrantLock(isFair);
    }

    @Override
    public synchronized E get(int index) {
//        final ReentrantLock mLocks = this.mLocks;
//        mLocks.lock();
        E e = this.lists.get(index);
//        mLocks.unlock();
        return e;
    }

    @Override
    public void add(E e) {
        checkNotNull(e);
//        final ReentrantLock mLocks = this.mLocks;
//        mLocks.lock();
        synchronized(this.lists) {
            try {
                while (this.lists.size() == this.limite) {
//                    System.out.println("============" + e + " will wait =============");
                    this.lists.wait();
//                    System.out.println("============" + e + " is break! =============");
                }
                if (this.lists.size() == 0) {
//                    System.out.println("============add " + e + " notifyAll =============");
                    this.lists.notifyAll();
                }
                this.lists.add(e);
            } catch (Exception e1) {
                e1.printStackTrace();
            } finally {
//            mLocks.unlock();
            }
        }
    }

    @Override
    public void remove(E e) {
        checkNotNull(e);
//        final ReentrantLock mLocks = this.mLocks;
//        mLocks.lock();
        synchronized(this.lists) {
            try {
                while (this.lists.size() == 0) {
                    this.lists.wait();
                }
                if (this.lists.size() == this.limite) {
//                    System.out.println("============remove " + e + " notifyAll =============");
                    this.lists.notifyAll();
                }
                this.lists.remove(e);
            } catch (Exception e1) {
                e1.printStackTrace();
            } finally {
//            mLocks.unlock();
            }
        }
    }

    @Override
    public synchronized void removeAll() {
//        final ReentrantLock mLocks = this.mLocks;
//        mLocks.lock();
        this.lists.clear();
//        mLocks.unlock();
    }

    @Override
    public int size() {
//        final ReentrantLock mLocks = this.mLocks;
//        mLocks.lock();
        synchronized(this.lists) {
            int length = this.lists.size();
//        mLocks.unlock();
            return length;
        }
    }

    private static void checkNotNull(Object v) {
        if (v == null)
            throw new NullPointerException();
    }
}
锁的实现方式
package blocks;

import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by maxi on 2017/11/8.
 */
public class ArrayBlockQueue<E> implements BlockQueues<E> {
    private final ArrayList<E> lists;
    private int limite;
    private ReentrantLock mLocks;
    private Condition notEmpty;
    private Condition notFull;

    public ArrayBlockQueue() {
        this(10, false);
    }

    public ArrayBlockQueue(int limite) {
        this(limite, false);
    }

    public ArrayBlockQueue(int limite, Boolean isFair) {
        this.limite = limite;
        lists = new ArrayList<>();
        mLocks = new ReentrantLock(isFair);
        notEmpty = mLocks.newCondition();
        notFull = mLocks.newCondition();
    }

    @Override
    public E get(int index) {
        final ReentrantLock mLocks = this.mLocks;
        mLocks.lock();
        E e = this.lists.get(index);
        mLocks.unlock();
        return e;
    }

    @Override
    public void add(E e) {
        checkNotNull(e);
//        final ReentrantLock mLocks = this.mLocks;
        mLocks.lock();
        try {
            while (this.lists.size() == this.limite) {
//                    System.out.println("============" + e + " will wait =============");
                notFull.await();
//                    System.out.println("============" + e + " is break! =============");
            }
//            if (this.lists.size() == 0) {
////                    System.out.println("============add " + e + " notifyAll =============");
//                this.lists.notifyAll();
//            }
            this.lists.add(e);
            notEmpty.signalAll();
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            mLocks.unlock();
        }
    }

    @Override
    public void remove(E e) {
        checkNotNull(e);
//        final ReentrantLock mLocks = this.mLocks;
        mLocks.lock();
        try {
            while (this.lists.size() == 0) {
//                    this.lists.wait();
                notEmpty.await();
            }
//                if (this.lists.size() == this.limite) {
////                    System.out.println("============remove " + e + " notifyAll =============");
//                    this.lists.notifyAll();
//                }
            this.lists.remove(e);
            notFull.signalAll();
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            mLocks.unlock();
        }
    }

    @Override
    public synchronized void removeAll() {
//        final ReentrantLock mLocks = this.mLocks;
        mLocks.lock();
        this.lists.clear();
        mLocks.unlock();
    }

    @Override
    public int size() {
//        final ReentrantLock mLocks = this.mLocks;
        mLocks.lock();
        int length = this.lists.size();
        mLocks.unlock();
        return length;
    }

    private static void checkNotNull(Object v) {
        if (v == null)
            throw new NullPointerException();
    }
}
main函数
package blocks;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created by maxi on 2017/11/8.
 */
public class BlockMain {
    public static void main(String[] args) throws InterruptedException {
//        BlockQueues<String> blockQueues = new ObjectBlockQueues<>();
        BlockingQueue<String> blockingQueues = new ArrayBlockingQueue<String>(10);
        BlockQueues<String> blockQueues = new ArrayBlockQueue<String>(10);
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i <= 20; i++) {
//                try {
//                    Thread.sleep(1000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                blockQueues.add("num" + i);
                System.out.println("thread 1 add " + i + " queue size = " + blockQueues.size());
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i <= 20; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                blockQueues.remove("num" + i);
                System.out.println("thread 2 remove " + i + " queue size = " + blockQueues.size());
            }
        });


        thread1.start();
        thread2.start();


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值