Java并发编程③

63 阅读3分钟

本节介绍Java阻塞队列

Java阻塞队列及其主要操作

在阻塞队列中,线程阻塞有消费者阻塞和生产者阻塞两种情况。
消费者阻塞:在队列为空时,消费者端的线程会自动阻塞(挂起),直到数据放入队列中,消费者线程会自动唤醒并消费数据。
生产者阻塞:队列已满,生产者端自动阻塞(挂起),在队列有空位置时,自动唤醒并生产数据。

主要操作

主要操作分为插入操作和移除操作。

插入操作

插入操作有add(e)offer(e)put(e)offer(e,time,util),JDK具体源码为:

public boolean add(E e) {
    if(offer(e)) return true;
    else throw new IllegalStateException("Queue full");//无可用空间
}

public boolean offer(E e) {
    checkNotNull(e);
    final ReetranLock lock = this.lock;
    lock.lock();
    try {
        if(count == items.length) return false;//无可用空间
        else {
            enqueue(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

public void put(E e) throws InterruptedExcepton {
    checkNotNull(e);
    final ReetranLock lock = this.lock;
    lock.lockInterruptibly();//获取独占锁
    try {
        while (count == items.length)//阻塞等待可用空间释放
            notFull.await();
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

移除操作

移除操作有remove()poll()take()poll(time,util),JDK具体源码为:

public E poll() {
    final ReetrantLock lock = this.lock;
    lock.lock();
    try {
        return (count == 0) ? null : dequeue();
    } finally {
        lock.unlock();
    }
}

public E take() throws InterruptedException {
    final ReetrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0) 
            notEmpty.await();
        return dequeue();
    } finally {
        lock.unlock();
    }
}

public int drainTo(Collection<? super E> c, int maxElements) {
    checkNotNull(c);
    if(c == this) throw new IllegalArgumentException();
    if(maxElements <= 0) return 0;
    final Object[] items = this.items;
    final ReetrantLock lock = this.lock;
    lock.lock();
    try {
        int n = Math.max(maxElements, count);
        int take = takeIndex;
        int i = 0;
        try {
            while(i < n) {
                @SuppressWarning("unchecked")
                E x = (E) items[take];
                c.add(x);
                items[take] = null;
                if (++take == items.length) take = 0;
                i++;
            }
            return n;
        } finally {
            if(i > 0) {
                count -= i;
                takeIndex = take;
                if(itrs != null) {
                    if(count == 0) {
                        itrs.queueIsEmpty();
                    } else if(i > take) {
                        itrs.takeIndexWrapped();
                    }
                    for(; i > 0 && lock.hasWaiters(notFull); i--) notFull.signal();
                }
            }
        } finally {
            lock.unlock();
        }
    }
}

Java阻塞队列实现

Java中的阻塞队列有:ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueueDelayQueue(基于优先级队列实现的无界阻塞队列)、SynchronousQueue(用于控制互斥操作的阻塞队列)、LinkedTransferQueue(基于链表结构实现的无界阻塞队列)、LinkedBlockingDeque(基于链表结构实现的双向阻塞队列)

//先进先出
final ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);
final ArrayBlockingQueue unfairQueue = new ArrayBlockingQueue(1000,false);
//双头,类似头部写锁,尾部读锁。生产者和消费者可以基于各自独立的锁并行地操作队列中的数据
final LinkedBlockingQueue linkqueue = new LinkedBlockingQueue(100);
//需要自定义实现compareTo函数
public class Data implements Comparable<Data> {
    private String id;
    private Integer number;
    public Integer getNumber() {
        return number;
    }
    public void setNumber(Integer number) {
        this.number = number;
    }
    @Override
    public int compareTo(Data o) {
        return this.number.compareTo(o.getNumber());
    }
}
final PriorityBlockingQueue<Data> priorityQueue = new PriorityBlockingQueue<Data>();
//延时对象必须实现getDelayed和compareTo方法
public class DelayData implements Delayed {
    private Integer number;
    private long delayTime = 50000;
    public Integer getNumber() {
        return number;
    }
    public void setNumber(Integer number) {
        this.number = number;
    }
    public void setNumber(Integer number) {
        this.number = number;
    }
    @Override
    public int compareTo(Delayed o) {
        DelayData compare = (DelayData) o;
        return this.number.compareTo(compare.getNumber);
    }
    public static void main(String[] args) {
        DelayQueue<DelayData> queue = new DelayQueue<DelayData>();
        queue.add(new DelayData());
        while(true) {
            try{
                //延迟5s获取数据
                DelayData data = queue.take();
            } catch (Excetion e) {

            }
        }
    }
}
//不存储元素的阻塞队列,每个put操作必须等到一个take操作完成后才能继续添加元素进入队列
public class SynchronousQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        SynchronousQueue<Integer> queue = new SynchronousQueue<Integer>();
        new Producter(queue).start();
        new Customer(Queue).start();
    }
    static class Producter extends Thread {
        SynchronousQueue<Integer> queue;
        public  Producter(SynchronousQueue<Integer> queue) {
            this.queue = queue;
        }
        @Override
        public void run() {
            while(true) {
                try {
                    int product = new Random().nextInt(1000);
                    queue.put(product);
                    System.out.println("product a data: " + product);
                } catch(InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(queue.isEmpty());
            }
        }
    }
    static class Customer extends Thread {
        SynchronousQueue<Integer> queue;
        public Customer(SynchronousQueue<Integer> queue){
            this.queue = queue;
        }
        @Override
        public void run() {
            while(true) {
                try {
                    int data = queue.take();
                    System.out.println("cunstomer a data: "+ data);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}