Java -- Blocking Queues

"BlockQueue<E>" 's common methods :

The blocking queue methods fall into three categories that differ by the action they perform when the queue is full or empty. If you use the queue as a thread management tool, use the "put" and "take" methods. The "add", "remove", and "element" operations throw an exception when you try to add to a full queue or get the head of an empty queue. Of cause, in a multithreaded program, the queue might become full or empty at any time, so you will instead want to use the "offer", "poll", and "peek" methods. These methods simply return with a failure indicator instead of throwing an exception if they cannot carry out their tasks.

java.util.concurrent.BlockingQueue<E> :
  void put(E element)
    // add the element, blocking if necessary.
  E take()
    // removes and returns the head element, blocking if necessary
  boolean offer(E element, long time, TimeUnit unit)
    // adds the given element and returns "true" if successful, blocking
    // if necessary until the element has been added or the time has elapsed.
  E poll(long time, TimeUnit unit)
    //removes and returns the head element, blocking if necessary until an element is available or the time has elapsed. 
    //Returns "null" upon failure.

The "java.util.concurrent" package supplies several variations of blocking queues. By default, the "LinkedBlockingQueue" has no upper bound on its capacity, but a maximum capacity can be optional specified. The "LinkedBlockingQueue" is a "double-ended" version. The "ArrayBlockingQueue" is constructed with a given capacity and an optional parameter to require fairness. If fairness is specified, then the longes-waiting threads are given preferential treatment. As always, fairness exacts a significant performance penalty, and you should only use it if your problem specifically requires it.

The "PriorityBlockingQueue" is a priority queue, not a first-in/first-out queue. Elements are removed in order of their priority. The queue has unbounded capacity, but retrival will block if the queue is empty.

A "DelayQueue" contains objects that implement the "Delayed" interface:

interface Delayed extends Comparable<Delayed> {
    long getDelay(TimeUnit unit);
}

The "getDelay" method returns the remaining delay  of the object. A negative value indicates that the delay has elapsed. Element can only be removed from a "DelayQueue" if their delay has elapsed. You also need to implement the "compareTo" method. The "DelayQueue" uses the method to sort the entries.

Java SE 7 adds a "TransferQueue" interface that allows a producer thread to wait until a consumer is ready to take an item. When a producer calls 

q.transer(item);

the call blocks until another thread removes it. The "LinkedTransferQueue" class implements this interface.

java.util.concurrent.ArrayBlockingQueue<E>:
  ArrayBlockingQueue(int capacity)
  ArrayBlockingQueue(int capacity, boolean fair)
    // constructs a blocking queue with the given capacity and fairness setting. 
    // The queue is implemented as a circular array.
java.util.concurrent.LinkedBlockingQueue<E>
java.util.concurrent.LinkedBlockingDequeue<E>
  LinkedBlockingQueue();
  LinkedBlockingDequeue();
    // construct an unbounded blocking queue or dequeue, implemented as a linked list.
  LinkedBlockingQueue(int capacity)
  LinkedBlockingDequeue(int capacity)
    // constructs a bounded blocking queue or dequeue with the given capacity, 
    // implemented as a linked list.
java.util.concurrent.DelayQueue<E extends Delayed>
  DelayQueue()
    // constructs an unbounded queue of "Delayed" elements. 
    // Only elements whose delay has expired can be removed from the queue.
java.util.concurrent.Delayed
  long getDelay(TimeUnit unit)
    // gets the delay for the object, measured in the given time unit.
java.util.concurrent.PriorityBlockingQueue<E>
  PriorityBlockingQueue()
  PriorityBlockingQueue(int initialCapacity)
  PriorityBlockingQueue(int initialCapacity, Comparator<? super E> comparator)
    //constructs an unbounded blocking priority queue implemented as a heap
    // Parameters  "initialCapacity"  The initial capacity. Default is 11.
    //             "comparator"       The comparator used to compare elements.
    //                                If not specified, the elements must implement the "Comparable" interface

The following example shows how to use a blocking queue to control a set of threads.

package ConcurrentTest;

import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created by lenovo on 2018/6/18.
 */
public class BlockingQueueTest {
    private static final int FILE_QUEUE_SIZE = 10;
    private static final int SEARCH_THREADS = 1000;
    private static final File DUMMY = new File("");
    private static BlockingQueue<File> queue = new ArrayBlockingQueue<>(FILE_QUEUE_SIZE);

    public static void enumerate(File directory) throws InterruptedException {
        File[] files = directory.listFiles();

        if (files != null) {

            for (File file : files) {

                if (file.isDirectory()) {
                    enumerate(file);
                } else {
                    queue.put(file);
                }

            }

        }

    }

    public static void search(File file, String key) {

        try (Scanner in = new Scanner(file, "UTF-8")) {
            int lineNumber = 0;

            while (in.hasNextLine()) {
                String line = in.nextLine();
                lineNumber++;

                if(line.contains(key)) {
                    System.out.printf("%s:%d:%s\n", file.getPath(), lineNumber, line);
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        System.out.println("Please Enter a directory: ");

        try (Scanner in = new Scanner(System.in)) {
            String directory = in.nextLine();

            System.out.println("Enter a key: ");
            String key = in.nextLine();

            Runnable enumerator = () -> {

                try {
                    enumerate(new File(directory));
                    queue.put(DUMMY);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }

            };

            new Thread(enumerator).start();

            for (int i = 0; i < SEARCH_THREADS; i++) {

                Runnable searchor = () -> {

                    try {
                        boolean isDone = false;

                        while (!isDone) {
                            File file = queue.take();

                            if (file == DUMMY) {    // using this trick to terminate the application is greate.
                                queue.put(file);
                                isDone = true;
                            } else {
                                search(file, key);
                            }

                        }

                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        e.printStackTrace();
                    }

                };

                new Thread(searchor).start();
            }

        } catch (Throwable e) {
            e.printStackTrace();
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值