JUC并发队列及应用

1.队列类型

阻塞队列:为了保证线程安全采用阻塞线程方式操作队列。
非阻塞队列:不阻塞线程操作队列。
有界队列: 队列长度有限制。
无界队列: 队列长度无限制。

2.无界非阻塞队列ConcurrentLinkedQueue:

实现结构:单向链表
实现线程安全方式:CAS【非阻塞】,poll出队和add/offer方法入队都是采用CAS机制来实现线程安全。
典型应用:Tomcat 中NioEndpoint使用ConcurrentLinkedQueue来接收请求。
特点:性能优越,适用于读多写少的场景。

3.无界阻塞队列LinkedBlockingQueue:

实现方式:单向链表
实现线程安全方式:take 和 put 对应【阻塞方法】,poll和offer对应【非阻塞方法】
如果take执行过程中队列为空/put队列已满则会陷入阻塞。poll/offer不会阻塞,而是直接返回null/false。
采用两个独占锁来实现头尾节点操作原子性,并都配备了一个条件队列,存放被阻塞的线程,结合入队出队可实现生产消费模型。【入队出队可同时运行
典型应用:JDK 线程池
特点:容量可达Integer.MAX_VALUE值,先进先出存取分离,并且能保证节点前后置不乱,删除节点时加两把锁,性能优越

4.有界阻塞队列ArrayBlockingQueue:

实现方式:数组
实现线程安全方式: 全局独占锁
典型应用:异步日志打印等
特点:同时只能有一个线程进行入队或者出队操作。size计算精确。

5.带优先级无界阻塞队列PriorityBlockingQueue:

实现方式:平衡二叉树堆 数组进行存储
实现线程安全方式:一个独占锁
典型应用:任务调度资源分配事件处理
特点:同时只能有一个线程进行入队或出队,但是由于是无界的,可一直put,不会陷入阻塞,内置使用CAS算法进行扩容操作,可自定以优先级比较规则。

6.无界阻塞延迟队列DelayQueue:

实现方式:优先级队列,且元素必须要实现Delayed接口
实现线程安全方式: 独占锁
典型应用:定时发送邮件定期数据清理订单支付延时发送消息缓存过期清除
特点:每个元素都有个过期时间、只有过期元素才会出队列。可实现延时功能。也可自定义元素比较规则。

7.额外补充

1.JDK7新增ThreadLocalRandom类,弥补传统Random类在多线程高并发请求下性能缺陷。
Random采用CAS机制来确保seed种子一定是基于上个seed种子生成的新种子,然后参与计算生成随机数。

   protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

CAS机制在高并发多线程下的缺陷就是不断自旋获取锁,大量占用CPU
为了解决这个问题,引入了ThreadLocalRandom类。将seed挪到Thread实例对象中。每个Thread都有一分属于自己的seed 也就是ThreadLocalRandomSeed
在这里插入图片描述
带大家看下这个ThreadLocalRandom类生成随机数nextInt()方法执行逻辑

	
    @Override
    public int nextInt() {
        return mix32(nextSeed());
    }
	// 因此这个nextSeed() 要保证原子性。
    final long nextSeed() {
        Thread t; long r; // read and update per-thread seed
        U.putLong(t = Thread.currentThread(), SEED,
                  r = U.getLong(t, SEED) + (t.threadId() << 1) + GOLDEN_GAMMA);
        return r;
    }
	// 逻辑计算是固定的。
    private static int mix32(long z) {
        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
        return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
    }


SEED来源于Thread 类中threadLocalRandomSeed 值。由于该是线程独立私有,因此多线程情况下不会发生生成同样随机数的情况,同时也避免了CAS所带来的锁竞争引发的CPU资源损耗。
在这里插入图片描述
2.SimpleDateFormat线程不安全,多线程情况下建议放入ThreadLocal中,记得使用完手动删除避免内存泄漏
3.Timer类定时任务执行多个TimerTask,如果存在一个方法抛出异常则会自动停止所有task,解决方案就是使用ScheduledThreadPoolExecutor中的schedule方法执行多个task。
4.需要复用且会被下游方法修改的参数要进行深复制,否则会出现错误结果。引用类型作为集合作为另一个集合的构造函数的参数,【引用传递】使用同一份引用,此时要采用深复制
5.线程池和线程构建需要补充业务相关的名称,便于排查异常。
6.线程池关闭记得调用shutdown关闭线程池。
7.线程池使用FutureTask,为了避免在DiscardPolicy/DiscardOldestPolicy策略下调用get方法陷入阻塞,建议使用带超时时间的get方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值