用Java实现一个简单的阻塞队列LinkedBlockingQueue

package mytest.others.other;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 阻塞队列
 * @Author lilong
 * @Date 2019-02-18 13:44
 */
public class SimpleLinkedBlockingQueue<E> {
    static class Node<E> {
        E item;
        Node<E> next;

        Node(E x) {
            item = x;
        }
    }
    private final int capacity;
    private final AtomicInteger count = new AtomicInteger();

    private Node<E> head; //头结点
    private Node<E> tail; //尾节点

    private Lock putLock = new ReentrantLock();
    private Condition putCond = putLock.newCondition();

    private Lock takeLock = new ReentrantLock();
    private Condition takeCond = takeLock.newCondition();


    public SimpleLinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

    public SimpleLinkedBlockingQueue(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException();
        }

        this.capacity = capacity;
        tail = head = new Node<E>(null);
    }


    public void put(E e) throws InterruptedException {
        putLock.lock();
        try {
            while (count.get() == capacity) {
                putCond.await();
            }
            enqueue(e);
            count.getAndIncrement();
        } finally {
            putLock.unlock();
        }

        takeLock.lock(); //signal的使用需要先获取锁
        try {
            takeCond.signal();
        } finally {
            takeLock.unlock();
        }
    }

    public E take() throws InterruptedException {
        E e;
        takeLock.lock();
        try {
            while (count.get() == 0) {
                takeCond.await();
            }
            e = dequeue();
            count.getAndDecrement();
        } finally {
            takeLock.unlock();
        }

        putLock.lock();
        try {
            putCond.signal();
        } finally {
            putLock.unlock();
        }

        return e;
    }

    private void enqueue(E e) {
        Node<E> newTail = new Node<>(e);
        tail.next = newTail; //新节点添加到列表末尾
        tail = newTail; //tail后移一位
    }

    private E dequeue() {
        E ret = head.next.item; //head节点是空的,仅作为哨兵使用,head.next才是第一个数据节点
        head = head.next;
        head.item = null;
        return ret;
    }

    //打印队列内容
    @Override
    public String toString() {
        List<E> arr = new ArrayList<>();

        Node<E> current = head.next;
        while (current != null && current.item != null) {
            arr.add(current.item);
            current = current.next;
        }

        return arr.toString();
    }
}

测试:

定义一个大小为3的阻塞队列,每次取出一个元素时都打印下完整的队列。

package mytest.others.other;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description TODO
 * @Author lilong
 * @Date 2019-01-27 20:45
 */
public class TestSimpleLinkedBlockingQueue {
    private static SimpleLinkedBlockingQueue<Integer> queue = new SimpleLinkedBlockingQueue<>(3);
    private static AtomicInteger ai = new AtomicInteger();

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        queue.put(ai.getAndIncrement());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        //打印队列现有元素
                        System.out.println(queue);
                        Integer e = queue.take();
                        System.out.println(e);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

打印结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值