9

标题几乎总结了它 - 我们可以创建一个java.util.Random(or SecureRandom) 的实例并在每次需要随机值时使用它,或者我们可以每次按需创建一个新实例。想知道哪一种是首选方式,为什么?

给出一些关于上下文的想法:随机值是在 HTTP 请求处理程序中生成的,每个请求一个,考虑到多线程,我正在寻找安全性和性能的最佳组合。

4

2 回答 2

7

这取决于。

创建单个实例显然更简单,应该是默认行为。两者RandomSecureRandom都是线程安全的,因此可以正常工作。首先做简单而正确的事情,然后根据预期的峰值竞争/峰值性能预算来衡量您的性能,并分析结果。

Random

如果您正在使用Random并且单实例方法太慢,ThreadLocalRandom请尽可能考虑使用。中的 JavaDocRandom很好地建议了它的用法:

的实例java.util.Random是线程安全的。但是,跨线程并发使用同一java.util.Random实例可能会遇到争用,从而导致性能下降。考虑改为ThreadLocalRandom在多线程设计中使用。

它只会为每个访问它的线程创建一个实例。Random/实例的创建成本ThreadLocalRandom并不疯狂,但它高于创建“普通”对象,因此您应该避免为每个传入请求创建新实例。每个线程创建一个通常是一个不错的最佳位置。

我想说的是,在具有池化线程的现代应用程序中,您几乎应该总是使用ThreadLocalRandom而不是Random- 随机性是相同的,但单线程性能要好得多。

SecureRandom

SecureRandom但是,如果您使用的是 ,ThreadLocalRandom则不是一种选择。再次,不要猜测,测量!也许使用 a 的单个共享实例SecureRandom就足够了。使用您预期的峰值竞争进行测试,如果安全随机实例成为瓶颈,然后才考虑改善这种情况的方法。

创建SecureRandom实例的成本非常高,因此您绝对不想为每个传入请求创建一个实例。

根据您的应用程序,aThreadLocal<SecureRandom>可能是一个选项。尽管如此,我认为这是一种矫枉过正的做法,并且可能首选类似于Striped类的方案(随机创建和访问 X个实例以帮助防止争用)。SecureRandom

于 2018-10-16T15:27:28.990 回答
2

If you need random numbers for information security, only a cryptographic RNG (such as java.security.SecureRandom) will do. And for any cryptographic RNG, the simplest approach is to use only one thread-safe instance of it for the entire application to use (note that SecureRandom is thread-safe according to the documentation); there is generally no benefit to creating multiple instances of a cryptographic RNG, as they will all eventually have to be initialized with high-entropy ("unpredictable") data.

Gathering such "unpredictable" data is not trivial, and at least for your application, you need not worry about that when you use SecureRandom, which largely does this for you and includes a setSeed method you can use to add extra data to supplement its randomness.

于 2018-10-18T23:59:34.473 回答