Random

根据 JDK 文档介绍, 它是线程安全的.

Instances of {@code java.util.Random} are threadsafe.

但文档中说, 在跨线程使用 Random 时, 它的性能比较低下.

ThreadLocalRandom

这个是在 JDK >= 1.7 时出现的, 当在多线程环境中使用 Random 时, 请考虑使用 ThreadLocalRandom. 因为它在多线程中相比 Random 性能更高. 一般的使用方式:

 ThreadLocalRandom.current().nextX(...)

性能基准对比

    @Benchmark
    public void testRandom(){
        GenerateIdUtils.generateBidId();
    }


    @Benchmark
    public void testThreadLocalRandom(){
        GenerateIdUtils.generateUnfrozenBidIdThreadLocal();
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(BenchmarkTest.class.getSimpleName())
                .forks(1)
                .warmupIterations(5)
                .measurementIterations(5)
                .build();
        new Runner(opt).run();
    }
    public static String generateBidId() {
        final String randomStr = getStringRandom(8);
        return BID_PREFIX + randomStr;
    }

    public static String generateUnfrozenBidId() {
        final String randomStr = getStringRandom(8);
        return BID_UNFROZEN_PREFIX + randomStr;
    }

    public static String generateUnfrozenBidIdThreadLocal() {
        final String randomStr = getStringRandomThraedLocal(8);
        return BID_UNFROZEN_PREFIX + randomStr;
    }

    // 生成随机数字和字母,
    private static String getStringRandomThraedLocal(final int length) {
        final StringBuilder buf = new StringBuilder();
        // 参数length,表示生成几位随机数
        final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
        for (int i = 0; i < length; i++) {
            // 输出字母还是数字
            if (threadLocalRandom.nextInt(2) % 2 == 0) {
                buf.append((char) (threadLocalRandom.nextInt(26) + 97));
            } else {
                buf.append(threadLocalRandom.nextInt(10));
            }
        }
        return buf.toString();
    }


    private static final Random random = new Random();
    // 生成随机数字和字母,
    private static String getStringRandom(final int length) {
        final StringBuilder buf = new StringBuilder();
        // 参数length,表示生成几位随机数
        for (int i = 0; i < length; i++) {
            // 输出字母还是数字
            if (random.nextInt(2) % 2 == 0) {
                buf.append((char) (random.nextInt(26) + 97));
            } else {
                buf.append(random.nextInt(10));
            }
        }
        return buf.toString();
    }

基准压测结果:

Benchmark                             Mode  Cnt     Score      Error   Units
BenchmarkTest.testRandom             thrpt    5  3586.838 ±  985.575  ops/ms
BenchmarkTest.testThreadLocalRandom  thrpt    5  5676.495 ± 2348.271  ops/ms