Multi-threaded programming learning six (blocking queue in Java).

Introduction

Blocking queue (BlockingQueue) means that when the queue is full, the queue will block the thread insert elements until the queue dissatisfied; when the queue is empty, the queue will get a thread blocking element until the queue is not empty. Blocking queue is used to store elements producers, consumers used to get the container element.

When the thread insert / get action because the queue is full / empty after blocking queue also provides a number of mechanisms to deal with, or throws an exception or return a special value, or the thread has been waiting for ...

The method / approach Throw an exception Returns the special value Has been blocked Timeout exit
Insertion method add(e) offer(e) put(e) offer(e, timeout, unit)
Removal Method remove(o) poll() take() poll(timeout, unit)
Inspection Method element() peek () - do not remove elements unavailable unavailable

tips: If you are unbounded blocking queue, then put the method will never be blocked; offer method always returns true.

In Java blocking queue:

ArrayBlockingQueue

ArrayBlockingQueue is a realization of an array bounded blocking queue. This queue orders elements in accordance with the principle of first in first out (FIFO), the thread does not guarantee fair access by default.

To control concurrent, Condition ReentrantLock by reentrant exclusive lock to achieve blocking.

public class ArrayBlockingQueueTest {

    /**
     * 1. 由于是有界阻塞队列,需要设置初始大小
     * 2. 默认不保证阻塞线程的公平访问,可设置公平性
     */
    private static ArrayBlockingQueue<String> QUEUE = new ArrayBlockingQueue<>(2, true);

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

        Thread put = new Thread(() -> {
            // 3. 尝试插入元素
            try {
                QUEUE.put("java");
                QUEUE.put("javaScript");
                // 4. 元素已满,会阻塞线程
                QUEUE.put("c++");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        put.start();
        Thread take = new Thread(() -> {
            try {
                // 5. 获取一个元素
                System.out.println(QUEUE.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        take.start();
        // 6 javaScript、c++
        System.out.println(QUEUE.take());
        System.out.println(QUEUE.take());
    }
}

LinkedBlockingQueue

LinkedBlockingQueue is a one-way linked list implementation bounded blocking queue. The default and maximum length of this queue is Integer.MAX_VALUE. This queue orders elements FIFO principle.

And ArrayBlockingQueue like using ReentrantLock to control concurrent, except that it uses two exclusive locks to control production and consumption, to control the production and consumption by takeLock and putLock two locks, without disturbing each other, as long as the queue is not full, production thread can always produce; as long as the queue is not empty, a thread can consume consumption, will not mutually exclusive lock because blocked.

tips: Because the use of a dual-lock, to avoid concurrent calculation is not accurate, the use of a variable AtomicInteger statistical elements of the total.

LinkedBlockingDeque

LinkedBlockingDeque is a doubly linked list of structures bounded blocking queue can be inserted and removed from both ends of the queue elements. It implements the interface BlockingDeque, more addFirst, addLast, offerFirst, offerLast, peekFirst peekLast and the like, to the end of a word First method for insert or remove the first acquisition element deque. Last end of a word to a method for insert or remove the last acquisition element deque.

LinkedBlockingDeque the Node multi-variable prev before pointing to a node, in order to achieve two-way queue. ArrayBlockingQueue the concurrency control and the like, with a single ReentrantLock to control concurrent. Because the double-ended queue head and tail can consumption and production, so the use of a shared lock.

Two-way blocking queue can be used in "work stealing" mode.

public class LinkedBlockingDequeTest {

    private static LinkedBlockingDeque<String> DEQUE = new LinkedBlockingDeque<>(2);

    public static void main(String[] args) {
        DEQUE.addFirst("java");
        DEQUE.addFirst("c++");
        // java
        System.out.println(DEQUE.peekLast());
        // java
        System.out.println(DEQUE.pollLast());
        DEQUE.addLast("php");
        // c++
        System.out.println(DEQUE.pollFirst());
    }
}

Tips: the Take () method call is takeFirst (), using the time should pay attention to.

PriorityBlockingQueue

PriorityBlockingQueue is a layer comprised of an array to achieve unbounded blocking queue, and with a sorting function. As the queue is unbounded, so the insert will never be blocked. Natural elements taken in ascending order by default. Custom class may implement the compareTo () method to specify the collation element, or a PriorityBlockingQueue is initialized, the parameters specified Comparator configured to sort the elements.

It is also based on ReentrantLock to control concurrent, as only will get blocked, so using only a Condition (only inform the consumer) to achieve.

public class PriorityBlockingQueueTest {

    private static PriorityBlockingQueue<String> QUEUE = new PriorityBlockingQueue<>();

    public static void main(String[] args) {
        QUEUE.add("java");
        QUEUE.add("javaScript");
        QUEUE.add("c++");
        QUEUE.add("python");
        QUEUE.add("php");
        Iterator<String> it = QUEUE.iterator();
        while (it.hasNext()) {
            // c++  javaScript  java  python  php
            // 同优先级不保证排序顺序
            System.out.print(it.next() + "  ");
        }
    }
}

DelayQueue

DelayQueue is a delay obtaining support elements of unbounded blocking queue. Queue using PriorityQueue to achieve. Queue element must implement Delayed interface elements by prioritizing delay, delay time shorter standing in the front, only to extract elements from the queue when the delay has expired.

And PriorityBlockingQueue Similarly, the underlying array is used to control a ReentrantLock concurrent.

Scenario:

  1. Design caching system: You can use DelayQueue save validity cache elements, use a thread loop query DelayQueue, once DelayQueue acquired from the elements, represent a valid cached.
  2. Timing task scheduling: tasks and execution time DelayQueue saved the day will be executed once DelayQueue get from the start to the task execution, such as TimerQueue is to use DelayQueue implemented.
public class DelayElement implements Delayed, Runnable {

    private static final AtomicLong SEQUENCER = new AtomicLong();
    /**
     * 标识元素先后顺序
     */
    private final long sequenceNumber;
    /**
     * 延迟时间,单位纳秒
     */
    private long time;

    public DelayElement(long time) {
        this.time = System.nanoTime() + time;
        this.sequenceNumber = SEQUENCER.getAndIncrement();
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(time - System.nanoTime(), NANOSECONDS);
    }

    @Override
    public int compareTo(Delayed other) {
        // compare zero if same object
        if (other == this) {
            return 0;
        }
        if (other instanceof DelayElement) {
            DelayElement x = (DelayElement) other;
            long diff = time - x.time;
            if (diff < 0) {
                return -1;
            } else if (diff > 0) {
                return 1;
            } else if (sequenceNumber < x.sequenceNumber) {
                return -1;
            } else {
                return 1;
            }
        }
        long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
        return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
    }

    @Override
    public void run() {
        System.out.println("sequenceNumber" + sequenceNumber);
    }

    @Override
    public String toString() {
        return "DelayElement{" + "sequenceNumber=" + sequenceNumber + ", time=" + time + '}';
    }
}
public class DelayQueueTest {

    private static DelayQueue<DelayElement> QUEUE = new DelayQueue<>();

    public static void main(String[] args) {
        // 1. 添加 10 个参数
        for (int i = 1; i < 10; i++) {
            // 2. 5 秒内随机延迟
            int nextInt = new Random().nextInt(5);
            long convert = TimeUnit.NANOSECONDS.convert(nextInt, TimeUnit.SECONDS);
            QUEUE.offer(new DelayElement(convert));
        }
        // 3. 查询元素排序 —— 延迟短的排在前面
        Iterator<DelayElement> iterator = QUEUE.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        // 4. 可观察到元素延迟输出
        while (!QUEUE.isEmpty()) {
            Thread thread = new Thread(QUEUE.poll());
            thread.start();
        }
    }
}

LinkedTransferQueue

LinkedTransferQueue is a linked list of structures TransferQueue unbounded blocking queue.

Using a large number of operations on CAS concurrency control, without the use of locks.

Compared to other blocking queue, LinkedTransferQueue more tryTransfer and transfer methods.

  1. transfer:. Transfers the element to a consumer, waiting if necessary to do so into the element must wait until consumer spending before returning.
  2. tryTransfer:. Transfers the element to a waiting consumer immediately, if possible if consumers are waiting for the consumer element, put the element passed passed to consumers. Otherwise, it returns false immediately, without waiting for the consumer.

SynchronousQueue

SynchronousQueue is not a storage element of blocking queue. Put each operation must wait for a take, otherwise continue to put the operation will be blocked.

SynchronousQueue default thread non fairness policy access queue, the lock is not used, all of the CAS operation is achieved through concurrent, very high throughput, and ArrayBlockingQueue with LinkedBlockingQueue above, very suitable for efficient transfer of some processing scenario. Executors.newCachedThreadPool () on the use of SynchronousQueue task delivery.

public class SynchronousQueueTest {

    private static class SynchronousQueueProducer implements Runnable {

        private BlockingQueue<String> blockingQueue;

        private SynchronousQueueProducer(BlockingQueue<String> queue) {
            this.blockingQueue = queue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    String data = UUID.randomUUID().toString();
                    System.out.println(Thread.currentThread().getName() + " Put: " + data);
                    blockingQueue.put(data);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private static class SynchronousQueueConsumer implements Runnable {

        private BlockingQueue<String> blockingQueue;

        private SynchronousQueueConsumer(BlockingQueue<String> queue) {
            this.blockingQueue = queue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    System.out.println(Thread.currentThread().getName() + " take(): " + blockingQueue.take());
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {

        final BlockingQueue<String> synchronousQueue = new SynchronousQueue<>();
        SynchronousQueueProducer queueProducer = new SynchronousQueueProducer(synchronousQueue);
        new Thread(queueProducer, "producer - 1").start();
        SynchronousQueueConsumer queueConsumer1 = new SynchronousQueueConsumer(synchronousQueue);
        new Thread(queueConsumer1, "consumer — 1").start();
        SynchronousQueueConsumer queueConsumer2 = new SynchronousQueueConsumer(synchronousQueue);
        new Thread(queueConsumer2, "consumer — 2").start();
    }
}

 
 

  1. Reference book: "Java concurrent programming art"
  2. Reference Hirofumi: Https://Www.Cnblogs.Com/konck/p/9473677.Html

Guess you like

Origin www.cnblogs.com/jmcui/p/11442616.html