线程同步:自定义阻塞队列—MyArrayBlockingQueue 关于ArrayBlockingQueue可以看这篇文章: 深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue

关于ArrayBlockingQueue可以看这篇文章:

深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue


下面就仿照ArrayBlockingQueue,写个简易版的阻塞队列MyArrayBlockingQueue:

/**
 * 自定义的 阻塞队列
 *
 * @param <T> 需要的对象类型
 */
public class MyArrayBlockingQueue<T> {

    /**
     * 对象数组,存对象
     */
    private final T[] items;

    /**
     * 锁
     */
    private Lock lock = new ReentrantLock();

    /**
     * 基于lock的 队列没有满 的条件。
     * 用于:队列满时 阻塞(await()),不满时唤醒(signal())
     */
    private Condition notFull = lock.newCondition();

    /**
     * 基于lock的 队列没有空 的条件。
     * 用于:队列空时 阻塞(await()),不空时唤醒(signal())
     */
    private Condition notEmpty = lock.newCondition();

    /**
     * 队列中数据的数量
     */
    private int count;

    /**
     * 待存的数据的位置
     */
    private int putIndex;

    /**
     * 待取的数据的位置
     */
    private int taskIndex;

    private String TAG = "MyArrayBlockingQueue";

    public MyArrayBlockingQueue(int size) {
        items = (T[]) new Object[size];
    }

    public void put(T t) {
        lock.lock();

        try {
            while (count == items.length) {
                //已经是满的,阻塞等待“不满”的线程
                Log.i(TAG, "put: 已满,等待中~");
                notFull.await();
            }
            Log.i(TAG, "put: 不满,插入~");

            items[putIndex] = t;
            if (++putIndex == items.length) {
                putIndex = 0;
            }
            count++;

            //已经确定不空了,唤醒 阻塞着的 等待“不空”的线程
            notEmpty.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public T take() {
        lock.lock();

        T t = null;
        try {
            while (count == 0) {
                //已经是空的,阻塞等待“不空”的线程
                Log.i(TAG, "take: 空的,等待中~");
                notEmpty.await();
            }
            Log.i(TAG, "take: 不空,取出~");
            t = items[taskIndex];
            if (++taskIndex == items.length) {
                taskIndex = 0;
            }
            count--;

            //已经确定不满了,唤醒 阻塞着的 等待“不满”的线程
            notFull.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

        return t;
    }

}

然后是创建生产者、消费者,即两个线程:

   /**
     * 生产者线程
     */
    private class ConsumerThread extends Thread {

        private final MyArrayBlockingQueue<Apple> arrayBlockingQueue;

        public ConsumerThread(MyArrayBlockingQueue<Apple> arrayBlockingQueue) {
            this.arrayBlockingQueue = arrayBlockingQueue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Log.i(TAG, "run: take, begin");
                    Apple apple = arrayBlockingQueue.take();
                    Log.i(TAG, "run: take, apple=" + apple);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生产者线程
     */
    private class ProducerThread extends Thread {

        private final MyArrayBlockingQueue<Apple> arrayBlockingQueue;

        public ProducerThread(MyArrayBlockingQueue<Apple> arrayBlockingQueue) {
            this.arrayBlockingQueue = arrayBlockingQueue;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                while (true) {
                    Apple apple = new Apple();
                    Log.i(TAG, "run: put, begin");
                    arrayBlockingQueue.put(apple);
                    Log.i(TAG, "run: put, apple=" + apple);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 产品
     */
    private class Apple {

    }

下面是使用MyArrayBlockingQueue实现“生产者-消费者”模式:

    /**
     * 生产者-消费者 模式
     * 实现方法:使用 {@Link MyArrayBlockingQueue}
     */
    private void threadTest4() {
        MyArrayBlockingQueue<Apple> arrayBlockingQueue = new MyArrayBlockingQueue<Apple>(3);
        new ProducerThread(arrayBlockingQueue).start();
        new ConsumerThread(arrayBlockingQueue).start();
    }

结果:

07-15 22:17:53.700 4835-5172/com.hfy.demo00 I/MainActivityhfy: run: take, begin--没有apple,消费者阻塞
07-15 22:17:55.701 4835-5171/com.hfy.demo00 I/MainActivityhfy: run: put, begin
07-15 22:17:55.702 4835-5171/com.hfy.demo00 I/MainActivityhfy: run: put, apple=com.hfy.demo00.MainActivity$Apple@5cd7457
    run: put, begin
07-15 22:17:55.702 4835-5171/com.hfy.demo00 I/MainActivityhfy: run: put, apple=com.hfy.demo00.MainActivity$Apple@4373b44
    run: put, begin
07-15 22:17:55.703 4835-5171/com.hfy.demo00 I/MainActivityhfy: run: put, apple=com.hfy.demo00.MainActivity$Apple@a2b242d
    run: put, begin
07-15 22:17:55.704 4835-5172/com.hfy.demo00 I/MainActivityhfy: run: take, apple=com.hfy.demo00.MainActivity$Apple@5cd7457 --有apple了,消费者消费
07-15 22:17:55.704 4835-5171/com.hfy.demo00 I/MainActivityhfy: run: put, apple=com.hfy.demo00.MainActivity$Apple@1324d62
    run: put, begin --队列满了,生产者阻塞
07-15 22:17:56.704 4835-5172/com.hfy.demo00 I/MainActivityhfy: run: take, begin
07-15 22:17:56.705 4835-5172/com.hfy.demo00 I/MainActivityhfy: run: take, apple=com.hfy.demo00.MainActivity$Apple@4373b44
07-15 22:17:56.705 4835-5171/com.hfy.demo00 I/MainActivityhfy: run: put, apple=com.hfy.demo00.MainActivity$Apple@1cafef3 --没满,插入




猜你喜欢

转载自blog.csdn.net/hfy8971613/article/details/81057790