下载框架,自定义实现一个阻塞优先队列。

我们在设计下载框架的时候,有时候我想改变下载任务的下载顺序,这个时候,我们涉及到一个下载队列得优先级。

既然是作下载,安卓这边的操作,大体技术方案,可能就是 线程池+ Runnable + 管理分发任务的队列。

我们先不考虑 service后台服务这一层,线程池的类别。

既然要写一个多线程环境下的操作的队列,那么需要考虑同步互斥,安全等。先看下jdk 提供API,有 ArrayBlockingQueue,

ConcurrentLinkedDeque(双向链表结构),ConcurrentLinkedQueue, 以及 LinkedBlockingQueue,LinkedBlockingDueue, PriorityBlockingQueue。。。我因为链表结构上,逻辑增删快,查询慢。因为一个下载任务,可能被随时取消或者增加,我想业务上选择这个单向链表结构不错。

既然可以自定义下载优先级,那么我想,我应该定义一个优先级的队列,所以看下 jdk源码下的LinkedBlockingQueue是怎么实现的,我们先看put方法。LinkedBlockingQueue 持有2把 ReentrantLock 锁,以及 2个 Condition对象。

看看 LinkedBlockingQueue源码:

先看put 方法。

    public void put(E e) throws InterruptedException {
//因为加入的节点 是空的,所以抛出异常,
        if (e == null) throw new NullPointerException();
//c=-1  初始化一个变量
        int c = -1;
//构造一个节点
        Node<E> node = new Node<E>(e);
//取出 成员变量的锁
        final ReentrantLock putLock = this.putLock;
// 定义一个 多线程安全的自增数
        final AtomicInteger count = this.count;
//开始加一把锁,可能是多线程环境下,其他线程也执行到这儿,然后当
//前线程谁先得到执行权,就直接把锁锁上,确保 put,offer操作,都只又一个线程进行 添加元素的操作
        putLock.lockInterruptibly();
       // 这儿的Try finally 是 jdk API 标准code 格式,防止线程唤醒
 try {
// 死循环判断是为了 防止假唤醒,jdk api 说的
            while (count.get() == capacity) {
// 如果 相等于linkedBlockingQueue的大小了,就把这个信号量给等待,
//那么当前线程就等待,多个线程执行 其他的put ,offer也是等待状态 
// not Full 为什么不可以再加入两个单词了, not full do addNode。没装满,还可以继续装的操作。等待
                notFull.await();
            }
//这里是加Node节点
            enqueue(node);
//C 表示 加入元素前的变量
            c = count.getAndIncrement();
// 如果 还有空间,notFull 信号量,表示可以让其他线程取抢 putLock锁的执行权了
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
//finally 当前运行线程,释放 putLock 锁,
            putLock.unlock();
        }
        if (c == 0)
// 如果c为0 那就说明会有take,或者offer操作阻塞,so 唤醒
            signalNotEmpty();
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值