37

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.

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!

time4tea
  • 2,169
  • 3
  • 16
  • 21
  • 2
    Why do you need an object pool first of all? In modern JVMs, creation of small objects is very, very cheap. Effective Java 2nd Ed. Item 5 recommends object pools only for heavyweight object like DB connections. – Péter Török Sep 03 '10 at 13:24
  • 5
    Well - i've got something like a database connection (but not a database connection), that I'd like to pool. – time4tea Sep 03 '10 at 13:30
  • (hence the bit about liveness validation) – time4tea Sep 03 '10 at 13:31
  • Can you list some more requirements that apache-commons can't meet? Seems like thread-safety is one of them. Any others? – The Alchemist Sep 03 '10 at 15:40
  • its not so much that it can't meet them... it just seems so... old. For example the interfaces are not generified, so you just get "Object". GenericObjectPool just feels like its kinda outdated and crufty. I just assumed there must be a 'cleaner' implementation around – time4tea Sep 03 '10 at 16:16
  • 1
    But the reason it's old is because they are pretty much unnecessary. Besides, old just implies stable ;) – Goibniu Sep 03 '10 at 16:20
  • 7
    why are they unnecessary? (not trolling!) these are expensive objects to external resources. you use a database connection pool, right? i want a (something else) connection pool... – time4tea Sep 03 '10 at 16:43
  • 2
    @Rulmeq "pretty much unnecessary" does not mean "never necessary". Library authors do not always get it right. – Thorbjørn Ravn Andersen Jun 22 '12 at 07:18
  • commons-pool supports generics now – artbristol Dec 19 '12 at 11:31
  • Here is a discussion about this in Guava: https://code.google.com/p/guava-libraries/issues/detail?id=683 – Fabian Zeindl May 22 '14 at 10:29

9 Answers9

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.

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).

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

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. If you can't find something that does everything you need out of the box, then extend an existing solution.
  3. Roll your own solution.
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 3
    Thanks for your answer - I'm fully aware that object creation, per se, is very cheap. I would never use an object pool to reuse object that exist only in memory. There be dragons. However, often objects represent some external expensive-to-create resource that you cannot create cheaply. Think database connection, or SSL connection. Its this type of think that I'd like to pool. I have updated the commons pool code. I'll post a patch here or something. – time4tea Sep 09 '10 at 08:42
  • 1
    @time4tea I was just trying to anchor my answer, not implying that you weren't aware. But thanks for the feedback and making the patch available. – Pascal Thivent Sep 09 '10 at 11:34
  • 2
    @PascalThivent I agree that object _creation_ is cheap, but object _initialization_ may be expensive. In other words, exactly the same as database connections. – Thorbjørn Ravn Andersen Aug 29 '12 at 13:52
  • 4
    I'm failing to see how object creation being cheap, which seems to be mentioned a lot in this question, has anything to do with object pools being made redundant. Cheapness has to be paired with the number of times it occurs, a grain of rice is cheap on its own but if you buy tonnes of it is expensive. Object pools are therefore useful when object creation becomes a bottleneck which varies depending on the number of initialisations and not just the cost of a single initialisation. – alex.p Mar 01 '19 at 10:35
  • Object creation is expensive. People conclude that object creation is cheap basing in microbenchmarks, where JVM can often elide object creation through escape analysis and even if not, cache effects or GC don't matter much. In real code object creation is slow and should be avoided as much as possible - object creation is often followed by a cache miss because it uses a chunk of memory that hasn't been touched for a while. It also forces GC to run more frequently, making it more likely to promote objects to the old gen, etc. This way you can slow your programs by 20x vs stack based code. – Piotr Kołaczkowski Feb 20 '20 at 08:22
7

Commons Pool is a good candidate for your project.

  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. use the patch that Pascal identified
  2. 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.
  3. Ugly Code - You are supposed to use it, not marry it.
  4. 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.
emory
  • 10,725
  • 2
  • 30
  • 58
  • 3
    I don't think concurrency is an implementation detail you shouldn't care about; you would only use an object pool if you want improved performance, so why would you use expensive monitor synchronization in this case when lock/wait free data structures are available? – BD at Rivenhill Aug 23 '12 at 16:49
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

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

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);
             }
           });
Community
  • 1
  • 1
NamshubWriter
  • 23,549
  • 2
  • 41
  • 59
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.

http://www.kbop.org

Jeremy Unruh
  • 649
  • 5
  • 10
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).

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.

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

vanOekel
  • 6,358
  • 1
  • 21
  • 56
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?.

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.

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

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.

Community
  • 1
  • 1
Christopher Klewes
  • 11,181
  • 18
  • 74
  • 102
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...

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.

jamiebarrow
  • 2,473
  • 3
  • 30
  • 51
-4

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

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?

nanda
  • 24,458
  • 13
  • 71
  • 90