java并发学习--第八章 JDK 8 新增的线程工具类

一、LongAdder

  LongAdder是JDK8AtomicLong的增强工具类,它与AtomicLong最大的不同就是:在多线程场景下,LongAdder中对单一的变量进行拆分成多个变量,这些变量分为两类base和Cell。base是基础值,默认一般为0;而Cell就是我们所拆分的值,它可以有多个。所以当获取LongAdder的值时就是把base和每个Cell的值相加。

  为什么要拆分成多个Cell呢?这是因为在多线程场景下,如果多个线程都在对同一个变量进行操作,为了使这个变量原子性,我们不得不对起加锁,这样就大大的降低了程序的性能。但是如果把这个变量拆分为多个Cell,虽然还是会给每个Cell加锁,但是线程访问的变量就是不是同一个了,可以进行异步操作。

  关于Cell的特点:

  1.Cell采用懒加载机制,这是因为Cell占的内存空间相对比较大的。开始只会创建Base,只有当有其他线程来竞争资源时,才会拆分为多个Cell;


  2.Cell的初始化值为2,每次扩容是2的N次方;

  3.Cell本质是一个数组,它的元素最大值为 CPU 核数;

  4.Cell 扩容条件: casCellsBusy 为 false 没有库容;有线程竞争资源;cell的数量没有超过 CPU的核数。
 

我们来看一个例子,用LongAdder声明一个值,使这个值加10000*10次,10为线程数:

  

public class ThreadLongAdder implements Runnable {

    //给线程方法传递一个参数
    static LongAdder count = new LongAdder();

    /**
     * 线程任务,将count的值相加10000*10
     */
    public void run() {
        System.out.println("当前线程获取count的值为:" + count);
        for (int i = 0; i < 10000; i++) {
            long num = 1l;
            count.add(num);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //创建多线程环境,这里创建了10个线程
        Thread[] thread = new Thread[10];
        //未创建的多线程中添加线程任务
        for (int i = 0; i < 10; i++) {
            thread[i] = new Thread(new ThreadLongAdder());
        }
        //启动每个线程任务
        for (int i = 0; i < 10; i++) {
            thread[i].start();
        }
        //join方法的作用是阻塞主线程,防止还没有计算完成,就开始输出count的值了
        for (int i = 0; i < 10; i++) {
            thread[i].join();
        }
        System.out.println("count计算的结果是:" + count);
    }
    
}

结果为:

  

猜你喜欢

转载自www.cnblogs.com/daijiting/p/11752377.html