4

I'm sure the correct answer to this depends on the type of pooled objects and the workload, so I'll detail my implementation a bit:

I have an ObjectPool used to pool long-running command-line processes. These processes communicate via stdin/stdout, and perform file/network operations. Many tasks complete much faster than others and may return processes to the pool quickly. All access to the pool must be thread-safe.

My question is, am I better off managing the pool with a LIFO/Stack, or a FIFO/ConcurrentLinkedQueue? My reasoning on both sides:

  • A stack keeps "hot" objects in play, where resources may remain cached/etc. for longer.
  • A FIFO balances calls more evenly between the processes, with each doing less work. Thanks!
Will
  • 24,082
  • 14
  • 97
  • 108
  • 9
    Or you could use a [`ConcurrentLinkedDeque`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedDeque.html) and combine the best of both worlds. – Jeffrey May 09 '12 at 19:43
  • So each process is specialized on something or they can all do the same thing? – Tudor May 09 '12 at 19:53
  • @Tudor: All can do the same thing. Any object is as good as the next to the borrow()er. – Will May 09 '12 at 20:41
  • @Jeffrey: What is the advantage to using this over a Stack? Just so I can "try both ways" easily, or better concurrency? – Will May 09 '12 at 20:42
  • @Will `Stack` is based off of `Vector`, which might as well be [deprecated](http://stackoverflow.com/questions/1386275/why-java-vector-class-is-considered-obsolete-or-deprecated). This will allow you to mix and match the two approaches, it can be both FIFO and LIFO. – Jeffrey May 10 '12 at 00:06
  • 1
    A [ConcurrentLinkedQueue](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html) uses a wait-free algorithm that would make it faster than the ConcurrentLinkedDeque. One reason (perhaps a poor one) to prefer the queue. – RalphChapin May 10 '12 at 19:35

2 Answers2

3

My first thought was: benchmark it! Both of your arguments seem reasonable. You should implement both strategies and do tests which of them results in the higher throughput.

The problem you describe in your question is similar to the process scheduling operating systems have to face. Hence, maybe it would be useful to make use of priorities. Use a PriorityQueue and assign different priorities to your tasks, which could change dynamically over time, for instance with Aging.

And last but not least, as was already pointed out in the comments you could try both ConcurrentLinkDeque and let some fetch the front objects and some the rear objects. Here, too, my advice is to try out and measure which balancing works best.

Konrad Reiche
  • 27,743
  • 15
  • 106
  • 143
1

It might not make a performance difference. Do whatever is easiest to code and makes your code easy to understand. A cache miss here and there isn't going to make a difference when you are dealing with command line processes doing file and network I/O... those are going to dominate by orders of magnitude.

amdn
  • 11,314
  • 33
  • 45