Scala 基36随机数

Scala 基36随机数,scala,Scala,这是一个短暂的应用程序,没有数据库,只在内存中保留原始->缩短的映射。如果我有以下每次调用的scala方法,生成一个值(然后用作缩短URL),然后保存在一个映射中(originalUrl->shortenUrl.从42亿(Integer.MAX_值)中选择)如果在多线程环境中调用,生成唯一缩短URL值的方法有什么缺点吗 def randomUrl: String = { Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 36

这是一个短暂的应用程序,没有数据库,只在内存中保留原始->缩短的映射。如果我有以下每次调用的scala方法,生成一个值(然后用作缩短URL),然后保存在一个映射中(originalUrl->shortenUrl.从42亿(Integer.MAX_值)中选择)如果在多线程环境中调用,生成唯一缩短URL值的方法有什么缺点吗

def randomUrl: String = {
   Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 36)
}

只有31位的信息可能会出现非唯一性问题。在生成大约64k个URL后,您可能会遇到第一次冲突。请使用更多位。而且,您无法确保您的种子与该方法不同,因此您最好创建一个随机数源并共享它


java.util.Random
是线程安全的,Scala只是转发到java实现,因此即使每次调用都不创建新的
Random
,在线程安全方面也应该没有问题。

您不应该有任何问题。下面的一行代码是Scala Random构造函数

def this() = this(new java.util.Random())
默认构造函数的OpenJDK源代码确实使用System.nanoTime(),但它不仅仅使用时间。它使用原子长度并调用compareAndSet(原子操作)来设置新值。如果该值已由另一个线程设置,它将重试另一个原子长度值,以使种子唯一

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

从Random的java页面(Scala包装了什么,我刚刚检查了源代码):“此构造函数将随机数生成器的种子设置为一个很可能不同于此构造函数的任何其他调用的值。”所以你的种子应该是fine@MillieSmith默认种子值是
System.currentTimeMillis
,因此,如果您同时精确地生成多个线程,那么它就不正常了time@user2066049不管我的第一句话,我看的源代码是错误的:-(@om-nom-nom看到我的答案了吗?你建议改为使用Long吗?@user2066049-至少。或者你可以生成,但随后验证它是否是唯一的。如果不是,请重新生成。