一个学习队列、生产者-消费者模式、多线程、同步的极佳的例子

15 篇文章 0 订阅
11 篇文章 0 订阅

发现一个极佳的学习队列、生产者-消费者模式、多线程、同步(当然也有模板)的极佳的例子。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 数组阻塞队列
 *
 * @param <E>
 */
class ArrayBlockingQueueDemon<E> {
    final ReentrantLock lock;

    /**
     * put元素时被阻塞的条件
     */
    final Condition putCondition;

    /**
     * take数据时被阻塞的条件
     */
    final Condition takeCondition;

    /**
     * 放元素的队列
     */
    final Object[] items;

    /**
     * take下一个元素的索引下标
     */
    int takeIndex;

    /**
     * put下一个元素的索引下标
     */
    int putIndex;

    /**
     * 队列中元素个数
     */
    int count;

    /**
     * 构造方法
     *
     * @param capacity 允许队列
     * @param fair     是否创建公平锁
     */
    public ArrayBlockingQueueDemon(int capacity, boolean fair) {
        if(capacity <= 0) {
            throw new IllegalArgumentException();
        }

        this.items = new Object[capacity];
        lock = new ReentrantLock(fair); //公平锁和不公平锁
        takeCondition = lock.newCondition();
        putCondition = lock.newCondition();
    }

    public void put(E e) throws InterruptedException {
        if(e == null) {
            throw new NullPointerException();
        }

        lock.lockInterruptibly();

        try {
            // 队列到达初始化上限时,不再允许向队列放数据,放数据的线程要等待
            // 此刻,当前线程会被添加到putCondition的阻塞队列里
            while (count == items.length) {
                putCondition.await();
            }
            // 入队
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        lock.lockInterruptibly();

        try {
            // 当队列没有数据时,拿数据的线程等待
            // 此该,当前线程会被添加到takeCondition的阻塞队列里
            while (count == 0) {
                takeCondition.await();
            }
            // 出队并返回
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    private void enqueue(E x) {
        items[putIndex] = x;
        ++putIndex;

        if(putIndex == items.length) {
            putIndex = 0;
        }

        count++;
        // 队列里增加元素了,可以唤醒取元素的线程了
        takeCondition.signal();
    }

    private E dequeue() {
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        ++takeIndex;

        if(takeIndex == items.length) {
            takeIndex = 0;
        }

        count--;
        // 队列元素减少了,腾出了位置,可唤醒放元素的线程了
        putCondition.signal();
        return x;
    }

    public static void  main(String[] args) throws InterruptedException {
        ArrayBlockingQueueDemon arrayBlockingQueueDemon = new ArrayBlockingQueueDemon(100, true); //

        for(int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
//                    Thread.sleep(1);
                    Integer integer = Integer.valueOf(finalI);
                    System.out.println(Thread.currentThread().getName() + " " + finalI + " running...");
                    arrayBlockingQueueDemon.put(integer);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }, "入队").start();
        }

        for(int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
//                    Thread.sleep(1);
                    System.out.println(Thread.currentThread().getName() + " " + finalI + " running...");
                    System.out.println(arrayBlockingQueueDemon.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }, "出队").start();
        }

        Thread.sleep(5000);
    }
}

这几个样例可以学的知识点包括:

1)队列:先进先出的表结构;

2)生产者-消费者模式:通过缓冲作为中间件,生产者发送数据,消费者读取数据;缓冲一般用队列。

3)多线程:线程是计算机中执行任务的最小单位(进程是拥有独立资源的最小单位)。执行线程获得CPU;线程阻塞会强占CPU;线程sleep或停止会退出CPU。多线程之间会进行任务切换,这牵涉对进程的管理,以及对CPU资源的占用。

4)同步:多线程之间同步,就是让任务取得一致。多线程同步,可以获得任务的一致性。多线程同步有多种机制,信号、临界区都是典型的机制。

当然,此样例还提供了泛型编程。

最后,对原代码出处表示致谢(Java锁详解之ReentrantLock_bug师姐的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值