标题几乎总结了它 - 我们可以创建一个java.util.Random
(or SecureRandom
) 的实例并在每次需要随机值时使用它,或者我们可以每次按需创建一个新实例。想知道哪一种是首选方式,为什么?
给出一些关于上下文的想法:随机值是在 HTTP 请求处理程序中生成的,每个请求一个,考虑到多线程,我正在寻找安全性和性能的最佳组合。
标题几乎总结了它 - 我们可以创建一个java.util.Random
(or SecureRandom
) 的实例并在每次需要随机值时使用它,或者我们可以每次按需创建一个新实例。想知道哪一种是首选方式,为什么?
给出一些关于上下文的想法:随机值是在 HTTP 请求处理程序中生成的,每个请求一个,考虑到多线程,我正在寻找安全性和性能的最佳组合。
这取决于。
创建单个实例显然更简单,应该是默认行为。两者Random
和SecureRandom
都是线程安全的,因此可以正常工作。首先做简单而正确的事情,然后根据预期的峰值竞争/峰值性能预算来衡量您的性能,并分析结果。
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
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.