[多线程] ThreadLocalRandom

436 阅读1分钟

引用:高并发情况下你还在用Random生成随机数

并发包中ThreadLocalRandom类原理剖析

1、实例化sun.misc.Unsafe

Unsafe 有一public 方法:getUnsafe() , 返回值是Unsafe的实例。如果直接调用会抛: Exception in thread "main" java.lang.SecurityException: Unsafe。 

有这样一段说明: Although the class and all methods are public, use of this class is limited because only trusted code can obtain instances of it. 所以只有java认为是安全的代码才可以获取Unsafe实例。

如果你尝试创建Unsafe类的实例,基于以下两种原因是不被允许的。

  • 1)、Unsafe类的构造函数是私有的;
  • 2)、虽然它有静态的getUnsafe()方法,但是如果你尝试调用Unsafe.getUnsafe(),会得到一个SecutiryException。这个类只有被JDK信任的类实例化。

但是这总会是有变通的解决办法的,一个简单的方式就是使用反射进行实例化

2、测试代码:

  private static Field fthreadLocalRandomSeed;    private static final sun.misc.Unsafe UNSAFE;    private static final long SEED;    static {        try {             // 反射 获取threadLocalRandomSeed             fthreadLocalRandomSeed = Thread.class.getDeclaredField("threadLocalRandomSeed");             fthreadLocalRandomSeed.setAccessible(true);             //获取unsafe对象            Field f = Unsafe.class.getDeclaredField("theUnsafe");            f.setAccessible(true);            UNSAFE = (Unsafe) f.get(0);            //虽然它有静态的getUnsafe()方法,但是如果你尝试调用Unsafe.getUnsafe(),会得到一个SecutiryException。这个类只有被JDK信任的类实例化。//          UNSAFE = sun.misc.Unsafe.getUnsafe();            Class<?> tk = Thread.class;            //获取threadLocalRandomSeed在thread中的偏移量            SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));        } catch (Exception e) {            throw new Error(e);        }    }    /**     * 使用反射 读写threadLocalRandomSeed成员     */    public static void byReflection() {        try {            long b = System.currentTimeMillis();            Thread t = Thread.currentThread();            fthreadLocalRandomSeed.set(t,0);            for (long i=0;i < 100000000;i++ ) {                fthreadLocalRandomSeed.set(t,(Long)fthreadLocalRandomSeed.get(t)+1);            }            long e = System.currentTimeMillis();            System.out.println("byReflection spend:" + (e-b) + "ms");        } catch (Exception e) {        }    }    /**     * 使用unsafe 读写threadLocalRandomSeed成员     */    public static void byUnsafe() {         UNSAFE.putLong(Thread.currentThread(),SEED,0);         long b = System.currentTimeMillis();         Thread t = Thread.currentThread();        for (long i = 0;i < 100000000; i++) {            UNSAFE.putLong(t,SEED,UNSAFE.getLong(t,SEED)+1);        }        long e = System.currentTimeMillis();        System.out.println("byUnsafe spend:" + (e-b) + "ms");    }    public static void main(String[] args) {        try {            byUnsafe();            byReflection();            System.out.println("===============");        } catch (Exception e) {            e.printStackTrace();        }    }