ThreadLocalRandom类原理分析

1、Random类及其局限性

public int nextInt(int bound) {
    if (bound <= 0)
        throw new IllegalArgumentException(BadBound);
    // 计算新的种子
    int r = next(31);
    int m = bound - 1;
    // 根据新的种子计算随机数
    if ((bound & m) == 0)  // i.e., bound is a power of 2
        r = (int)((bound * (long)r) >> 31);
    else {
        for (int u = r;
             u - (r = u % bound) + m < 0;
             u = next(31))
            ;
    }
    return r;
}
protected int next(int bits) {
    long oldseed, nextseed;
    // 这是一个原子性的变量
    AtomicLong seed = this.seed;
    do {
        // (1)、获取老的种子
        oldseed = seed.get();
        // (2)、计算出新的种子
        nextseed = (oldseed * multiplier + addend) & mask;
    // (3)、CAS操作更新老的种子
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}

Random小结:

  • 面试:多线程下Random存在什么样的问题?

每个Random实例里面都有一个原子性的种子变量用来记录当前的种子值,当要生成新的随机数时需要根据当前的种子计算新的种子并更新种子变量。当在多线程环境下,多个线程会竞争同一个原子变量的更新操作,由于原子变量的更新时CAS操作,同时只有一个线程会成功,所以会造成大量线程进行自旋重试,从而降低并发性能。

可能出现的症状:
如果并发请求非常多,自旋锁一直重试,那么CPU会一直飙升。

2、ThreadLocalRandom

public static ThreadLocalRandom current() {
    if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
        localInit();
    return instance;
}
static final void localInit() {
    int p = probeGenerator.addAndGet(PROBE_INCREMENT);
    int probe = (p == 0) ? 1 : p; // skip 0
    long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
    Thread t = Thread.currentThread();
    UNSAFE.putLong(t, SEED, seed);
    UNSAFE.putInt(t, PROBE, probe);
}

这个方法用来创建ThreadLocalRandom随机数生成器,如果当前线程中threadLocalRandomProbe的变量值为0,则说明是第一次调用current方法,那么就调用localInit方法初始化种子变量。

这里使用了延迟初始化,在localInit方法中,并没有初始化种子变量,而是在需要生成随机数的时候再生成种子变量,这是一种优化。

public int nextInt(int bound) {
    if (bound <= 0)
        throw new IllegalArgumentException(BadBound);
    // 生成种子
    int r = mix32(nextSeed());
    int m = bound - 1;
    if ((bound & m) == 0) // power of two
        r &= m;
    else { // reject over-represented candidates
        for (int u = r >>> 1;
             u + m - (r = u % bound) < 0;
             u = mix32(nextSeed()) >>> 1)
            ;
    }
    return r;
}
final long nextSeed() {
    Thread t; long r; // read and update per-thread seed
    // 生成新种子(获取当前线程种子 + 种子增量)
    UNSAFE.putLong(t = Thread.currentThread(), SEED,
                   r = UNSAFE.getLong(t, SEED) + GAMMA);
    return r;
}

mix32是一个固定的算法,这里重点看下nextSeed方法,当第一次调用的时候进行初始化,获取当前线程threadLocalRandomSeed的值(第一次默认值为0) + 种子增量,如果不是第一次那么获取旧种子的值 + 种子增量生成新的种子变量并设置回去。这样的话多线程环境下就避免了竞争,因为threadLocalRandomSeed是Thread的一个变量,属于线程级别。

 

<think>好的,我现在需要帮用户找到Anaconda 2025年最新版的安装教程。首先,用户提到了引用[1]是关于Anaconda在Win10下的使用心得,里面提到了配置和包含的应用,但可能已经过时了,因为用户需要的是2025年的最新版教程。引用[2]是有关SATA和Linux的背景文章,可能不相关。 接下来,我应该考虑Anaconda的官方渠道,比如官方网站,通常最新版的安装指南会在那里发布。虽然现在可能还没有2025年的版本,但用户可能假设到那时安装步骤不会有太大变化,只是版本号不同。需要提醒用户访问官网获取最新信息。 然后,安装步骤通常包括下载安装包、运行安装程序、配置环境变量等。需要注意不同操作系统(Windows、macOS、Linux)的差异。例如,在Linux下可能需要使用bash脚本安装,而Windows是exe文件。 还要考虑用户可能遇到的问题,比如环境变量设置、安装后的验证、以及常见错误的解决方法。例如,安装完成后在命令行输入conda --version是否显示正确版本。 另外,用户可能对Anaconda的组件感兴趣,比如Navigator、Conda包管理等,可以简要提及。同时,生成的相关问题需要围绕安装后的配置、环境管理、版本差异等,帮助用户进一步了解。 最后,确保按照用户的要求使用正确的LaTeX格式,比如行内公式用$...$,独立公式用$$...$$,但当前问题不涉及数学公式,所以可能不需要使用。但需要检查是否有其他需要格式化的地方,确保回答结构清晰,步骤详细,符合用户的系统级指令。</think>### Anaconda 2025最新版安装教程 #### 1. 访问Anaconda官网 进入[Anaconda官方网站](https://www.anaconda.com/),导航至"Downloads"页面,选择操作系统(Windows/macOS/Linux)对应的**2025.x.x版本**安装包[^1]。 #### 2. 安装步骤(以Windows为例) ```bash # 验证安装成功的示例命令 conda --version # 应输出 conda 2025.x.x ``` 1. **运行安装程序** - 双击下载的`.exe`(Windows)/`.pkg`(macOS)/`.sh`(Linux)文件 - 注意勾选"Add Anaconda to my PATH environment variable"(建议新手勾选) 2. **高级配置** - 安装路径建议保持默认`C:\ProgramData\Anaconda3`(Windows) - 对于Linux用户,可通过终端执行: ```bash bash ~/Downloads/Anaconda3-2025.x-Linux-x86_64.sh ``` #### 3. 验证安装 $$ \text{在命令行执行} \quad \boxed{\texttt{conda list}} \quad \text{应显示已安装的包列表} $$ #### 4. 组件说明 - **Anaconda Navigator**:图形化包管理界面 - **Conda**:核心命令行工具(支持创建虚拟环境) - **Jupyter Notebook**:预装的计算笔记本工具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值