Blocking queues, you know?

Keywords: Java

  1. Is there a good side to blocking queues?

  2. Have to block, how do you manage

The blocking queue is first a queue.
When the blocking queue is empty, the operation of fetching elements from the queue will be blocked. When the queue is full, the operation of adding elements to the queue will be blocked.

Why Blocking Queue:
The advantage is that we don't need to care when we need to block threads and when we need to wake them up, because all the BlockingQueue is done by itself.

Where to use it:

Producer-consumer model:
Traditional edition:

class ShareData {
    private int v;

    ReentrantLock lock = new ReentrantLock();
    Condition condition_increment = lock.newCondition();
    Condition condition_decrement = lock.newCondition();

    public void decrement() {
        try {
            lock.lock();
            while (true) {
                while (v == 0) {
                    condition_decrement.await();
                }
                v--;
                System.out.println(Thread.currentThread().getName() + " Consumption:" + v);
                condition_increment.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void increment() {
        try {
            lock.lock();
            while (true) {
                while (v != 0) {
                    condition_increment.await();
                }
                v++;
                System.out.println(Thread.currentThread().getName() + " Production:" + v);
                condition_decrement.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

	public static void main(String[] args) {
        ShareData shareData = new ShareData();
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                shareData.increment();
            }, "increment-" + 1).start();
        }

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                shareData.decrement();
            }, "decrement-" + i).start();
        }
    }

Blocking queue edition:

class ShareData {

    private volatile boolean FLAG = true;
    private BlockingQueue<String> blockingQueue;
    private AtomicInteger atomicInteger = new AtomicInteger();

    public ShareData(BlockingQueue<String> blockingQueue) {
        this.blockingQueue = blockingQueue;
    }

    public void increment() {
        try {
            while (FLAG) {
                String s = atomicInteger.incrementAndGet() + "";
                boolean offer = blockingQueue.offer(s);
                if(offer) {
                    System.out.println(Thread.currentThread().getName() + " Successful production:" + s);
                } else {
                    System.out.println(Thread.currentThread().getName() + " Production failure:" + s);
                }
                TimeUnit.SECONDS.sleep(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("flag=false, Production call-off");
    }

    public void decrement() {
        while (FLAG) {
            try {
                String poll = blockingQueue.poll(2, TimeUnit.SECONDS);
                if(poll == null || poll.equals("")) {
                    System.out.println(Thread.currentThread().getName() + " No consumable product for more than two seconds, consumption stops");
                    return;
                } else {
                    System.out.println(Thread.currentThread().getName() + " Consumption Success:" + poll);
                    TimeUnit.SECONDS.sleep(1);
                }
//                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("flag=false, Consumption call-off");
    }

    public void callStop() {
        this.FLAG = false;
    }

}

	public static void main(String[] args) {
        ShareData shareData = new ShareData(new ArrayBlockingQueue<String>(3));
        for (int i = 0; i < 3 ; i++) {
            new Thread(() -> {
                shareData.increment();
            }, "increment-" + 1).start();
        }

        for (int i = 0; i < 1; i++) {
            new Thread(() -> {
                shareData.decrement();
            }, "decrement-" + i).start();
        }

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        shareData.callStop();
    }

increment-1 Successful production:1
increment-1 Successful production:2
increment-1 Successful production:3
decrement-0 Consumption Success:1
increment-1 Successful production:4
increment-1 Production failure:5
decrement-0 Consumption Success:2
increment-1 Successful production:6
increment-1 Production failure:7
increment-1 Production failure:8
decrement-0 Consumption Success:3
increment-1 Successful production:9
increment-1 Production failure:10
increment-1 Production failure:11
increment-1 Production failure:12
decrement-0 Consumption Success:4
increment-1 Successful production:13
increment-1 Production failure:14
increment-1 Production failure:15
decrement-0 Consumption Success:6
flag=false, Production call-off
flag=false, Production call-off
flag=false, Consumption call-off
flag=false, Production call-off

Thread pool:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {}

Message Middleware



  • Array BlockingQueue: A bounded blocking queue consisting of an array structure
  • LinkedBlockingQueue: A bounded (but default size is Integer.MAX_VALUE) blocking queue consisting of a linked list structure
  • Priority Blocking Queue: Unbounded Blocking Queue Supporting Priority Sorting
  • DelayQueue: Delayed unbounded blocking queue implemented with priority queue
  • SynchronousQueue: A blocking queue that does not store elements, that is, a queue of individual elements (each put operation must wait for a take operation, otherwise it cannot continue to add elements, and vice versa)
  • LinkedTransferQueue: An unbounded blocking queue consisting of a linked list structure
  • Linked Blocking Deque: A bidirectional blocking queue consisting of a linked list structure

The Core Method of BlockQueue

  • add(e) Insert. When the queue is full, inserting the add element into the queue throws java.lang.IllegalStateException.
  • remove(), when the queue is empty, removing elements into the queue throws java.util.NoSuchElementException
  • element() checks the queue, returns the header element, and throws java.util.NoSuchElementException when the queue is empty
public static void main(String[] args) {
    BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(3);

    System.out.println("1. " + blockingQueue.add("a"));
    System.out.println("2. " + blockingQueue.add("b"));
    System.out.println("3. " + blockingQueue.add("c"));

    try {
        System.out.println("4. " + blockingQueue.add("d"));
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
    System.out.println("10. " + blockingQueue.element());

    System.out.println("5. " + blockingQueue.remove());
    System.out.println("6. " + blockingQueue.remove());
    System.out.println("7. " + blockingQueue.remove());
    try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
    try {
        System.out.println("8. " + blockingQueue.remove());
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
    try {
        System.out.println("9. " + blockingQueue.element());
    } catch (Exception e) {
        e.printStackTrace();
    }
}


1. true
2. true
3. true
java.lang.IllegalStateException: Queue full
	at java.util.AbstractQueue.add(AbstractQueue.java:98)
	at java.util.concurrent.ArrayBlockingQueue.add(ArrayBlockingQueue.java:312)
	at com.suanfa.booking.BlockingQueueDemo.main(BlockingQueueDemo.java:21)
10. a
5. a
6. b
7. c
java.util.NoSuchElementException
	at java.util.AbstractQueue.remove(AbstractQueue.java:117)
	at com.suanfa.booking.BlockingQueueDemo.main(BlockingQueueDemo.java:33)
java.util.NoSuchElementException
	at java.util.AbstractQueue.element(AbstractQueue.java:136)
	at com.suanfa.booking.BlockingQueueDemo.main(BlockingQueueDemo.java:39)
  • offer(e) adds elements, returns true successfully, and false failures
  • poll() removes the element, returns true successfully, and false failures
  • peek() probe team head element return
public static void main(String[] args) {
    BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(3);

    System.out.println("1. " + blockingQueue.offer("a"));
    System.out.println("2. " + blockingQueue.offer("b"));
    System.out.println("3. " + blockingQueue.offer("c"));
    System.out.println("4. " + blockingQueue.offer("d"));

    System.out.println("10. " + blockingQueue.peek()); //Exploration Team Head Element

    System.out.println("5. " + blockingQueue.poll());
    System.out.println("6. " + blockingQueue.poll());
    System.out.println("7. " + blockingQueue.poll());
    System.out.println("8. " + blockingQueue.poll());

    System.out.println("9. " + blockingQueue.peek());
}


1. true
2. true
3. true
4. false
10. a
5. a
6. b
7. c
8. null
9. null
  • put(e) insert element queues into full-time blocking
  • take() removes element queues for space-time blocking
  • offer(e, time, unit) inserts elements, blocking when the queue is full, returning false beyond the set time
    blockingQueue.offer("d", 2L, TimeUnit.SECONDS)
  • poll(time, unit) removes elements, queues block space-time, and returns false beyond the set time
public static void main(String[] args) {
    SynchronousQueue<Integer> synchronousQueue = new SynchronousQueue<>();

    new Thread(() -> {
        try {
            System.out.println(Thread.currentThread().getName() + " put " + 1);
            synchronousQueue.put(1);
            TimeUnit.SECONDS.sleep(1); //Keeping the printing order is independent of the experimental principle.
            System.out.println(Thread.currentThread().getName() + " put " + 2);
            synchronousQueue.put(2);
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName() + " put " + 3);
            synchronousQueue.put(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    },"AA").start();

    new Thread(() -> {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName() + " get " + synchronousQueue.take());

            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName() + " get " + synchronousQueue.take());

            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName() + " get " + synchronousQueue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }, "BB").start();
}


AA put 1
BB get 1
AA put 2
BB get 2
AA put 3
BB get 3

Posted by bimo on Mon, 09 Sep 2019 02:10:02 -0700