在Java中找不到现代的Object Pool实现

时间:2021-12-26 00:56:04

I'm looking for a modern implementation of an object pool in Java. I can see the apache commons one, but to be honest, I'd rather one that uses generics, and the concurrency stuff from more recent versions of java.

我正在寻找Java中对象池的现代实现。我可以看到apache commons one,但说实话,我更倾向于使用泛型,以及来自更新版本java的并发内容。

Does the commons pool really work well? The code looks pretty, erm, ugly.

公共泳池真的运作良好吗?代码看起来很漂亮,呃,丑陋。

I'd need something that allows custom liveness validation etc etc.

我需要一些允许自定义活动验证等的东西。

Thanks!

9 个解决方案

#1


19  

I can see the apache commons one, but to be honest, I'd rather one that uses generics, and the concurrency stuff from more recent versions of java.

我可以看到apache commons one,但说实话,我更倾向于使用泛型,以及来自更新版本java的并发内容。

Well, the fact is that this kind of projects (generic object pools) don't get much traction because there is little need for them nowadays (object creation is cheap). This probably explains why you don't see much of them (and actually, I'm only aware of Commons Pool).

嗯,事实是这种项目(通用对象池)没有太多牵引力,因为现在对它们的需求很少(对象创建很便宜)。这可能解释了为什么你没有看到太多(实际上,我只知道Commons Pool)。

That being said, if generics is your primary concern, you could patch Commons Pool, see POOL-83, it has a patch attached.

话虽如此,如果泛型是您的主要关注点,您可以修补Commons Pool,请参阅POOL-83,它附有补丁。

Does the commons pool really work well? The code looks pretty, erm, ugly.

公共泳池真的运作良好吗?代码看起来很漂亮,呃,丑陋。

It does have a few known bugs (four) but, to my knowledge, it works. And regarding the last sentence, well, if you think you can write something better, and if you have the time for that, why not just doing it?

它确实有一些已知的错误(四个),但据我所知,它的工作原理。关于最后一句,好吧,如果你认为你可以写出更好的东西,如果你有时间,为什么不做呢?

I'd need something that allows custom liveness validation etc etc.

我需要一些允许自定义活动验证等的东西。

You don't have an infinite number of options. Either

您没有无限多个选项。或

  1. Find something that does everything you need (I don't know such a library, which doesn't mean there isn't any).
  2. 找到能满足你所​​需要的东西(我不知道这样的库,这并不代表没有任何东西)。

  3. If you can't find something that does everything you need out of the box, then extend an existing solution.
  4. 如果您无法找到能够满足您需求的所有东西,那么请扩展现有解决方案。

  5. Roll your own solution.
  6. 推出自己的解决方案。

#2


7  

Commons Pool is a good candidate for your project.

Commons Pool是您项目的理想选择。

  1. Generics Interface - The most obvious problem with commons pool is its pre-generics interface. There are a number of ways you can get around this. You can
    1. do casting;
    2. implement a parallel interface that does the casting for you; or
    3. 实现一个为你做铸造的并行接口;要么

    4. use the patch that Pascal identified
    5. 使用Pascal识别的补丁

  2. 泛型接口 - 公共池最明显的问题是它的预泛化接口。有很多方法可以解决这个问题。你可以做铸造;实现一个为你做铸造的并行接口;或使用Pascal识别的补丁

  3. Concurrency Stuff from more recent java - This is an implementation detail you should not care about. If the concurrency is correct, then it does not matter how correctness was achieved. Alternatively, a pool implementation that uses the more recent stuff but whose concurrency is wrong is still a poor candidate.
  4. 来自更新的Java的并发资料 - 这是您不应该关心的实现细节。如果并发性是正确的,那么实现正确性无关紧要。或者,使用更新的东西但其并发性错误的池实现仍然是一个不好的候选者。

  5. Ugly Code - You are supposed to use it, not marry it.
  6. 丑陋的代码 - 你应该使用它,而不是嫁给它。

  7. Custom Liveness Validation - Implement the validateObject to test the liveness of objects. Dead objects will be destroyed. You can also implement a Cron task to periodically borrow and return objects - forcing the timely elimination of dead objects.
  8. 自定义活动验证 - 实现validateObject以测试对象的活跃度。死亡的物体将被摧毁。您还可以实现Cron任务以定期借用和返回对象 - 强制及时消除死对象。

#3


7  

It's hard to make a recommendation without knowing what features you need.

如果不知道您需要什么功能,很难提出建议。

If the number of objects in the pool is fixed, you can use a BlockingQueue as in this example from the question mentioned by @codedevour

如果池中的对象数量是固定的,您可以使用@codedevour提到的问题中的BlockingQueue,如本例所示

If the values you want to pool can be associated with a key, you can use MapMaker from Guava

如果要池的值可以与键关联,则可以使用Guava中的MapMaker

ConcurrentMap<Key, Connection> connections = new MapMaker()
       .concurrencyLevel(32)
       .softKeys()
       .weakValues()
       .expiration(30, TimeUnit.MINUTES)
       .evictionListener(
           new MapEvictionListener<Key, Connection>() {
             public onEviction(Key key, Connection connection) {
               connection.close();
             } 
           });
       .makeComputingMap(
           new Function<Key, Connection>() {
             public Connection apply(Key key) {
               return createConnection(key);
             }
           });

#4


3  

Checkout KBOP. It's a thread safe blocking single key to single object or single key to multi object pool. It's lightweight and add no extra dependencies.

结帐KBOP。它是一个线程安全的阻止单个对象的单个键或多个对象池的单个键。它是轻量级的,不添加额外的依赖项。

http://www.kbop.org

#5


2  

This seems to be related to your question, maybe you should really consider to write a object pool by your own. Does this basic Java object pool work?.

这似乎与您的问题有关,也许您应该考虑自己编写一个对象池。这个基本的Java对象池是否有效?

Pooling was initially introduced as a tuning action for the slow performance of object creation and garbage collection in particular. On a modern JVM > 1.4 pooling is no more needed for the optimization of memory management in a typical business application. It can even have a negative effect on the garbage collector performance. In special cases, like creating millions of instances in every method call, it could still pay off.

池最初是作为调整操作引入的,特别是对象创建和垃圾收集的缓慢性能。在现代JVM> 1.4池中,不再需要优化典型业务应用程序中的内存管理。它甚至可能对垃圾收集器性能产生负面影响。在特殊情况下,比如在每个方法调用中创建数百万个实例,它仍然可以获得回报。

Instance pooling, however is still interesting for objects with slow custom "post construction". In some cases you want to inject some dependencies after the object creation, read some configuration etc. This can be slow and doesn't have to be performed over and over again. In such cases object pooling will improve the overall performance.

然而,对于具有慢定制“后期构造”的对象,实例池仍然是有趣的。在某些情况下,您希望在创建对象后注入一些依赖项,读取一些配置等。这可能很慢,不必一次又一次地执行。在这种情况下,对象池将提高整体性能。

Adam Bien -- Object Pooling Can Be Still Useful - For Entirely Different Reasons

Adam Bien - 对象池可能仍然有用 - 完全不同的原因

What do you think of enhancing the commons Pool Framework? You could do some refactoring and add the generic part, would be nice for others too.

您如何看待增强公共池框架?你可以做一些重构并添加通用部分,对其他人也会很好。

#6


2  

Yet another pool (yapool) contains a generic pool implementation with the option to act on pool events via listeners (example). This provides a lot of flexibility in customizing pool behavior, add functions and diagnosing pool resource usage. Alternatively, you can also extend a pool implementation to add your own desired behavior (example). This should be relatively straightforward since pool implementations already extend each other (Basic --> Bound --> Pruned).

另一个池(yapool)包含一个通用池实现,可以选择通过侦听器对池事件进行操作(示例)。这为自定义池行为,添加功能和诊断池资源使用提供了很大的灵活性。或者,您也可以扩展池实现以添加您自己想要的行为(示例)。这应该相对简单,因为池实现已经相互扩展(Basic - > Bound - > Pruned)。

To start, you can use a simple BoundPool and set your own factory (see for example the "LongFactory" in the earlier mentioned pool events example), or just use an ObjectPool.

首先,您可以使用简单的BoundPool并设置自己的工厂(例如,参见前面提到的池事件示例中的“LongFactory”),或者只使用ObjectPool。

Yapool has no "synchronized" blocks and is pretty fast.

Yapool没有“同步”块,速度非常快。

#7


1  

There is a object pool implementation in http://code.google.com/p/spf4j/ I find it a better implementation than the one in apache commons. Code is not so ugly, and it performs better...

在http://code.google.com/p/spf4j/中有一个对象池实现我发现它比apache commons中的实现更好。代码不是那么难看,它表现得更好......

#8


0  

For the generics side, why not just use the non-generic library, and create a wrapper that you use to access the non-generic library that takes care of the casting? That way there's a single place where the casting is done, which will at least clean up the code a bit.

对于泛型方面,为什么不使用非泛型库,并创建一个包装器,用于访问负责转换的非通用库?这样就有一个完成转换的地方,这至少会清理代码。

#9


-3  

To pool is the traditional way, to cache is the modern way. And there are many modern implementation of cache out there.

池是传统的方式,缓存是现代的方式。并且有很多现代的缓存实现。

To learn the different between those two, you can read this: http://www.informit.com/guides/content.aspx?g=java&seqNum=104

要了解这两者之间的差异,您可以阅读:http://www.informit.com/guides/content.aspx?g = java&seqNum = 104

My view is, we can use a cache library to pool our objects but not the other way around. Just don't forget to re-initialize the object after we get it from the cache. So why bother having two different animals (cache and pool) if you can achieve all just using one?

我的观点是,我们可以使用缓存库来汇集我们的对象,而不是相反。在我们从缓存中获取对象后,不要忘记重新初始化对象。那么,如果能够实现所有只使用一个动物,为什么还要为两个不同的动物(缓存和池)烦恼呢?

#1


19  

I can see the apache commons one, but to be honest, I'd rather one that uses generics, and the concurrency stuff from more recent versions of java.

我可以看到apache commons one,但说实话,我更倾向于使用泛型,以及来自更新版本java的并发内容。

Well, the fact is that this kind of projects (generic object pools) don't get much traction because there is little need for them nowadays (object creation is cheap). This probably explains why you don't see much of them (and actually, I'm only aware of Commons Pool).

嗯,事实是这种项目(通用对象池)没有太多牵引力,因为现在对它们的需求很少(对象创建很便宜)。这可能解释了为什么你没有看到太多(实际上,我只知道Commons Pool)。

That being said, if generics is your primary concern, you could patch Commons Pool, see POOL-83, it has a patch attached.

话虽如此,如果泛型是您的主要关注点,您可以修补Commons Pool,请参阅POOL-83,它附有补丁。

Does the commons pool really work well? The code looks pretty, erm, ugly.

公共泳池真的运作良好吗?代码看起来很漂亮,呃,丑陋。

It does have a few known bugs (four) but, to my knowledge, it works. And regarding the last sentence, well, if you think you can write something better, and if you have the time for that, why not just doing it?

它确实有一些已知的错误(四个),但据我所知,它的工作原理。关于最后一句,好吧,如果你认为你可以写出更好的东西,如果你有时间,为什么不做呢?

I'd need something that allows custom liveness validation etc etc.

我需要一些允许自定义活动验证等的东西。

You don't have an infinite number of options. Either

您没有无限多个选项。或

  1. Find something that does everything you need (I don't know such a library, which doesn't mean there isn't any).
  2. 找到能满足你所​​需要的东西(我不知道这样的库,这并不代表没有任何东西)。

  3. If you can't find something that does everything you need out of the box, then extend an existing solution.
  4. 如果您无法找到能够满足您需求的所有东西,那么请扩展现有解决方案。

  5. Roll your own solution.
  6. 推出自己的解决方案。

#2


7  

Commons Pool is a good candidate for your project.

Commons Pool是您项目的理想选择。

  1. Generics Interface - The most obvious problem with commons pool is its pre-generics interface. There are a number of ways you can get around this. You can
    1. do casting;
    2. implement a parallel interface that does the casting for you; or
    3. 实现一个为你做铸造的并行接口;要么

    4. use the patch that Pascal identified
    5. 使用Pascal识别的补丁

  2. 泛型接口 - 公共池最明显的问题是它的预泛化接口。有很多方法可以解决这个问题。你可以做铸造;实现一个为你做铸造的并行接口;或使用Pascal识别的补丁

  3. Concurrency Stuff from more recent java - This is an implementation detail you should not care about. If the concurrency is correct, then it does not matter how correctness was achieved. Alternatively, a pool implementation that uses the more recent stuff but whose concurrency is wrong is still a poor candidate.
  4. 来自更新的Java的并发资料 - 这是您不应该关心的实现细节。如果并发性是正确的,那么实现正确性无关紧要。或者,使用更新的东西但其并发性错误的池实现仍然是一个不好的候选者。

  5. Ugly Code - You are supposed to use it, not marry it.
  6. 丑陋的代码 - 你应该使用它,而不是嫁给它。

  7. Custom Liveness Validation - Implement the validateObject to test the liveness of objects. Dead objects will be destroyed. You can also implement a Cron task to periodically borrow and return objects - forcing the timely elimination of dead objects.
  8. 自定义活动验证 - 实现validateObject以测试对象的活跃度。死亡的物体将被摧毁。您还可以实现Cron任务以定期借用和返回对象 - 强制及时消除死对象。

#3


7  

It's hard to make a recommendation without knowing what features you need.

如果不知道您需要什么功能,很难提出建议。

If the number of objects in the pool is fixed, you can use a BlockingQueue as in this example from the question mentioned by @codedevour

如果池中的对象数量是固定的,您可以使用@codedevour提到的问题中的BlockingQueue,如本例所示

If the values you want to pool can be associated with a key, you can use MapMaker from Guava

如果要池的值可以与键关联,则可以使用Guava中的MapMaker

ConcurrentMap<Key, Connection> connections = new MapMaker()
       .concurrencyLevel(32)
       .softKeys()
       .weakValues()
       .expiration(30, TimeUnit.MINUTES)
       .evictionListener(
           new MapEvictionListener<Key, Connection>() {
             public onEviction(Key key, Connection connection) {
               connection.close();
             } 
           });
       .makeComputingMap(
           new Function<Key, Connection>() {
             public Connection apply(Key key) {
               return createConnection(key);
             }
           });

#4


3  

Checkout KBOP. It's a thread safe blocking single key to single object or single key to multi object pool. It's lightweight and add no extra dependencies.

结帐KBOP。它是一个线程安全的阻止单个对象的单个键或多个对象池的单个键。它是轻量级的,不添加额外的依赖项。

http://www.kbop.org

#5


2  

This seems to be related to your question, maybe you should really consider to write a object pool by your own. Does this basic Java object pool work?.

这似乎与您的问题有关,也许您应该考虑自己编写一个对象池。这个基本的Java对象池是否有效?

Pooling was initially introduced as a tuning action for the slow performance of object creation and garbage collection in particular. On a modern JVM > 1.4 pooling is no more needed for the optimization of memory management in a typical business application. It can even have a negative effect on the garbage collector performance. In special cases, like creating millions of instances in every method call, it could still pay off.

池最初是作为调整操作引入的,特别是对象创建和垃圾收集的缓慢性能。在现代JVM> 1.4池中,不再需要优化典型业务应用程序中的内存管理。它甚至可能对垃圾收集器性能产生负面影响。在特殊情况下,比如在每个方法调用中创建数百万个实例,它仍然可以获得回报。

Instance pooling, however is still interesting for objects with slow custom "post construction". In some cases you want to inject some dependencies after the object creation, read some configuration etc. This can be slow and doesn't have to be performed over and over again. In such cases object pooling will improve the overall performance.

然而,对于具有慢定制“后期构造”的对象,实例池仍然是有趣的。在某些情况下,您希望在创建对象后注入一些依赖项,读取一些配置等。这可能很慢,不必一次又一次地执行。在这种情况下,对象池将提高整体性能。

Adam Bien -- Object Pooling Can Be Still Useful - For Entirely Different Reasons

Adam Bien - 对象池可能仍然有用 - 完全不同的原因

What do you think of enhancing the commons Pool Framework? You could do some refactoring and add the generic part, would be nice for others too.

您如何看待增强公共池框架?你可以做一些重构并添加通用部分,对其他人也会很好。

#6


2  

Yet another pool (yapool) contains a generic pool implementation with the option to act on pool events via listeners (example). This provides a lot of flexibility in customizing pool behavior, add functions and diagnosing pool resource usage. Alternatively, you can also extend a pool implementation to add your own desired behavior (example). This should be relatively straightforward since pool implementations already extend each other (Basic --> Bound --> Pruned).

另一个池(yapool)包含一个通用池实现,可以选择通过侦听器对池事件进行操作(示例)。这为自定义池行为,添加功能和诊断池资源使用提供了很大的灵活性。或者,您也可以扩展池实现以添加您自己想要的行为(示例)。这应该相对简单,因为池实现已经相互扩展(Basic - > Bound - > Pruned)。

To start, you can use a simple BoundPool and set your own factory (see for example the "LongFactory" in the earlier mentioned pool events example), or just use an ObjectPool.

首先,您可以使用简单的BoundPool并设置自己的工厂(例如,参见前面提到的池事件示例中的“LongFactory”),或者只使用ObjectPool。

Yapool has no "synchronized" blocks and is pretty fast.

Yapool没有“同步”块,速度非常快。

#7


1  

There is a object pool implementation in http://code.google.com/p/spf4j/ I find it a better implementation than the one in apache commons. Code is not so ugly, and it performs better...

在http://code.google.com/p/spf4j/中有一个对象池实现我发现它比apache commons中的实现更好。代码不是那么难看,它表现得更好......

#8


0  

For the generics side, why not just use the non-generic library, and create a wrapper that you use to access the non-generic library that takes care of the casting? That way there's a single place where the casting is done, which will at least clean up the code a bit.

对于泛型方面,为什么不使用非泛型库,并创建一个包装器,用于访问负责转换的非通用库?这样就有一个完成转换的地方,这至少会清理代码。

#9


-3  

To pool is the traditional way, to cache is the modern way. And there are many modern implementation of cache out there.

池是传统的方式,缓存是现代的方式。并且有很多现代的缓存实现。

To learn the different between those two, you can read this: http://www.informit.com/guides/content.aspx?g=java&seqNum=104

要了解这两者之间的差异,您可以阅读:http://www.informit.com/guides/content.aspx?g = java&seqNum = 104

My view is, we can use a cache library to pool our objects but not the other way around. Just don't forget to re-initialize the object after we get it from the cache. So why bother having two different animals (cache and pool) if you can achieve all just using one?

我的观点是,我们可以使用缓存库来汇集我们的对象,而不是相反。在我们从缓存中获取对象后,不要忘记重新初始化对象。那么,如果能够实现所有只使用一个动物,为什么还要为两个不同的动物(缓存和池)烦恼呢?