重用 java.util.Random 实例 vs 每次都创建一个新实例 [英] Reusing java.util.Random instance vs creating a new instance every time

查看:59
本文介绍了重用 java.util.Random 实例 vs 每次都创建一个新实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

解决方案

视情况而定.

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

随机

如果您使用 Random 并且单实例方法太慢,请尽可能考虑使用 ThreadLocalRandom.Random 中的 JavaDoc 很好地说明了它的用法:

<块引用>

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

它只会为每个访问它的线程创建一个实例.Random/ThreadLocalRandom 实例的创建成本并不疯狂,但它比创建普通"对象的成本要高,因此您应该避免创建新实例对于每个传入的请求.每个线程创建一个通常是一个不错的选择.

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

SecureRandom

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

创建一个 SecureRandom 实例的成本非常高,所以你绝对不想为每个传入的请求创建一个.

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

The title pretty much summarizes it - we can create one instance of java.util.Random (or SecureRandom) and use it every time we need a random value or we can create a new instance every time on demand. Wondering which one is the preferred way and why?

To give some idea about the context: the random value is being generated inside an HTTP request handler, one per request, and I'm looking for the best combination for security and performance considering multi-threading.

解决方案

It depends.

Creating a single instance is obviously simpler and should be the default behaviour. Both Random and SecureRandom are threadsafe, and will therefore work just fine. First do the simple and correct thing that works, then measure your performance against your expected peak contention / peak perf budget, and analyze the results.

Random

If you're using Random and the single instance approach is too slow, consider using ThreadLocalRandom if possible. The JavaDoc in Random suggests its usage nicely:

Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.

It will only create an instance for each thread accessing it. The creation cost of a Random / ThreadLocalRandom instance is not insane, but it is higher than the creation of a "normal" object, so you should probably avoid creating a new instance for each incoming request. Creating one per thread is generally a nice sweet spot.

I would say that in modern applications with pooled threads, you should almost always use ThreadLocalRandom instead of Random - the randomness is the same, but the single-thread performance is much better.

SecureRandom

If you're using SecureRandom, though, ThreadLocalRandom is not an option. Again, do not guess, measure! Maybe using a single shared instance of a SecureRandom will be good enough. Test with your expected peak contention, and if the secure random instance turns out to be a bottleneck, only then think about ways to improve the situation.

Creating a SecureRandom instance is very costly, so you absolutely do not want to create one for each incoming request.

Depending on your application, a ThreadLocal<SecureRandom> may be an option. Still, I think that's an overkill, and a scheme similar to the Striped class (with X SecureRandom instances created and accessed randomly to help prevent contention) may be preferred.

这篇关于重用 java.util.Random 实例 vs 每次都创建一个新实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆