LinkedBlockingQueue与生产消费模型

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/wangwei708846696/article/details/80579502
生产消费模型

ReentrantLock提供了tryLock方法,tryLock调用的时候,如果锁被其他线程持有,那么tryLock会立即返回,返回结果为false;如果锁没有被其他线程持有,那么当前调用线程会持有锁,并且tryLock返回的结果为true。

对于ReentrantLock来说,还有一个十分实用的特性,它可以同时绑定多个Condition条件,以实现更精细化的同步控制。
ReentrantLock使用方式如下:

Lock lock = new ReentrantLock();
lock.lock();
try{
}finally{
    lock.unlock();
}
  • int getHoldCount():查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
  • int getQueueLength():返回正等待获取此锁定的线程估计数。比如有5个线程,1个线程首先执行await()方法,那么在调用getQueueLength方法后返回值是4,说明有4个线程在等待lock的释放。
  • int getWaitQueueLength(Condition condition):返回等待此锁定相关的给定条件Condition的线程估计数。比如有5个线程,每个线程都执行了同一个condition对象的await方法,则调用getWaitQueueLength(Condition condition)方法时返回的int值是5。
  • boolean hasQueuedThread(Thread thread):查询指定线程是否正在等待获取此锁定。
  • boolean hasQueuedThreads():查询是否有线程正在等待获取此锁定。
  • boolean hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的condition条件。
  • boolean isFair():判断是不是公平锁。
  • boolean isHeldByCurrentThread():查询当前线程是否保持此锁定。
  • boolean isLocked():查询此锁定是否由任意线程保持。
  • void lockInterruptibly():如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
public class ProducerConsumerByLock {
    private static final int CAPACITY = 5;
    private static final Lock lock = new ReentrantLock();
    private static final Condition fullCondition = lock.newCondition();     //队列满的条件
    private static final Condition emptyCondition = lock.newCondition();        //队列空的条件


    public static void main(String args[]){
        Queue<Integer> queue = new LinkedList<Integer>();

        Thread producer1 = new Producer("P-1", queue, CAPACITY);
        Thread producer2 = new Producer("P-2", queue, CAPACITY);
        Thread consumer1 = new Consumer("C1", queue, CAPACITY);
        Thread consumer2 = new Consumer("C2", queue, CAPACITY);
        Thread consumer3 = new Consumer("C3", queue, CAPACITY);

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }

    /**
     * 生产者
     */
    public static class Producer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;
        int i = 0;

        public Producer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){

                //获得锁
                lock.lock();
                while(queue.size() == maxSize){
                    try {
                        System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                        //条件不满足,生产阻塞
                        fullCondition.await();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println("[" + name + "] Producing value : +" + i);
                queue.offer(i++);

                //唤醒其他所有生产者、消费者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //释放锁
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 消费者
     */
    public static class Consumer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;

        public Consumer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){
                //获得锁
                lock.lock();

                while(queue.isEmpty()){
                    try {
                        System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
                        //条件不满足,消费阻塞
                        emptyCondition.await();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                int x = queue.poll();
                System.out.println("[" + name + "] Consuming value : " + x);

                //唤醒其他所有生产者、消费者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //释放锁
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
LinkedBlockingQueue
public void put(E e) throws InterruptedException {
    if (e == null) throw new NullPointerException();
    int c = -1;
    Node<E> node = new Node<E>(e);
    final ReentrantLock putLock = this.putLock;//private final ReentrantLock putLock = new ReentrantLock();
    final AtomicInteger count = this.count;//private final AtomicInteger count = new AtomicInteger();
    putLock.lockInterruptibly();//如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
    try {
        while (count.get() == capacity) {
            notFull.await();//如果达到设置的总量则执行满锁等待
        }
        enqueue(node);//Node<E> last = last.next = node;添加到队列最后
        c = count.getAndIncrement();
        if (c + 1 < capacity)
            notFull.signal();//队列个数不超过总数时释放满锁对应notify
    } finally {
        putLock.unlock();//解锁putLock
    }
    if (c == 0)
        signalNotEmpty();//解锁空锁
}
public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;//private final AtomicInteger count = new AtomicInteger();
    final ReentrantLock takeLock = this.takeLock;//private final ReentrantLock takeLock = new ReentrantLock();
    takeLock.lockInterruptibly();//如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
    try {
        while (count.get() == 0) {//队列空时进行等待
            notEmpty.await();
        }
        x = dequeue();//从队列头部取出一个值
        c = count.getAndDecrement();
        if (c > 1)
            notEmpty.signal();//个数大于一说明还可以继续取所以唤醒空锁
    } finally {
        takeLock.unlock();//解锁takeLock
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

这两段代码可以看出来,ReentrantLock相当于synchronized的作用锁住这段代码不能同时被多线程访问,而Condition则提供唤醒等待机制。一个Condition对应一个等待和一个解锁,使用是:在当前线程不满足业务条件时候等待,其他线程满足业务条件了释放唤醒该条件。

引用:https://blog.csdn.net/u010983881/article/details/78554671

猜你喜欢

转载自blog.csdn.net/wangwei708846696/article/details/80579502