yeah it works as expected but it is not what we (often) want, typically RejectedExecutionException are an issue
in fact that's the only difference between all cases: when will RejectedExecutionException be thrown the linked case is the one avoiding it the more (but using more memory).. solution are always a compromise ;) *Romain Manni-Bucau* *Twitter: @rmannibucau* *Blog: http://rmannibucau.wordpress.com* 2012/8/21 Bjorn Danielsson <bjorn-apa...@lists.cuspycode.com> > Can you give an example when a SynchronousQueue would block > too much? In my tests it works exactly like I would expect a > bounded queue with a size of zero to behave. The thread pool > reaches MaximumPoolSize and then a RejectedExecutionException > is thrown. For a LinkedBlockingQueue with size 1, exactly the > same thing happens but one submission later, since one element > was queued before the thread pool started to expand. > > For the array vs bounded linked queue, I can't see how there > are any practical differences for a ThreadPoolExecutor except > for how memory is used to store the Runnable pointers in the > queue. > > -- > Björn Danielsson > Cuspy Code AB > > > Romain Manni-Bucau <rmannibu...@gmail.com> wrote: > > hmm, > > > > on the jvm implementation i personnaly think it is a good implementation > > but the unbounded linkedblockingqueue case is not the one for which the > > impl was designed IMO that's why it sounds strange i think. > > > > about the conf i prefer to not switch to synchrous queue too easily since > > it can blocks too much (could be a pity for sthg asynchronous ;)). > > > > finally between array or linked case the main difference will be the > array > > case is less tolerant but i agree in an application well configured it > > shouldn't make any difference. > > > > *Romain Manni-Bucau* > > *Twitter: @rmannibucau* > > *Blog: http://rmannibucau.wordpress.com* > > > > > > > > > > 2012/8/21 Bjorn Danielsson <bjorn-apa...@lists.cuspycode.com> > > > >> In my opinion this is a bit overkill, at least the options for > >> using DelayQueue and PriorityBlockingQueue. They require the > >> Runnable queue elements to implement the Delayed and Comparable > >> interfaces, respectively. I don't see how to make use of that in > >> an EJB method call. > >> > >> I looked at the Sun ThreadPoolExecutor docs and have now played > >> a little with it in a standalone program. I honestly think the > >> design is a bit bizarre. I would expect the thread pool to expand > >> to max capacity before tasks are put in the wait queue. For the > >> purpose of optimizing CPU core utilization, the number of threads > >> in the operating system run-queue is the only important number, > >> not the number of provisioned threads in a JVM thread pool. > >> But this is slightly off-topic here. > >> > >> I believe it's enough to have just one more configuration > >> property for TomEE: AsynchronousPool.QueueSize. If this is 0, > >> let the container use a SynchronousQueue. Otherwise use a > >> LinkedBlockingQueue with the specified capacity. That way it's > >> possible to have any of the three queueing strategies mentioned > >> in the ThreadPoolExecutor javadocs. I can't imagine a situation > >> where using an ArrayBlockingQueue instead of a bounded > >> LinkedBlockingQueue in TomEE really makes a big difference, > >> but I could be wrong about that. > >> > >> -- > >> Björn Danielsson > >> Cuspy Code AB > >> > >> > >> David Blevins <david.blev...@gmail.com> wrote: > >> > On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote: > >> > > >> >> that's because we use a linked blocking queue > >> >> > >> >> maybe we should make it configurable, not sure... > >> > > >> > > >> > Made it configurable. Code is basically: > >> > > >> > public static AsynchronousPool create(AppContext appContext) { > >> > final Options options = appContext.getOptions(); > >> > > >> > final String id = appContext.getId(); > >> > final int corePoolSize = > >> options.get("AsynchronousPool.CorePoolSize", 10); > >> > final int maximumPoolSize = > >> Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), > corePoolSize); > >> > final Duration keepAliveTime = > >> options.get("AsynchronousPool.KeepAliveTime", new Duration(60, > >> TimeUnit.SECONDS)); > >> > final BlockingQueue queue = > >> options.get("AsynchronousPool.QueueType", > QueueType.LINKED).create(options); > >> > > >> > return new AsynchronousPool(id, corePoolSize, maximumPoolSize, > >> keepAliveTime, queue); > >> > } > >> > > >> > private static enum QueueType { > >> > ARRAY, > >> > DELAY, > >> > LINKED, > >> > PRIORITY, > >> > SYNCHRONOUS; > >> > > >> > public BlockingQueue create(Options options) { > >> > switch (this) { > >> > case ARRAY: { > >> > return new > >> ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100)); > >> > } > >> > case DELAY: { > >> > return new DelayQueue(); > >> > } > >> > case LINKED: { > >> > return new > >> LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize", > >> Integer.MAX_VALUE)); > >> > } > >> > case PRIORITY: { > >> > return new PriorityBlockingQueue(); > >> > } > >> > case SYNCHRONOUS: { > >> > return new > >> SynchronousQueue(options.get("AsynchronousPool.QueueFair", false)); > >> > } > >> > default: { > >> > // The Options class will throw an error if the > user > >> supplies an unknown enum string > >> > // The only way we can reach this is if we add a > new > >> QueueType element and forget to > >> > // implement it in the above switch statement. > >> > throw new IllegalArgumentException("Unknown > >> QueueType type: " + this); > >> > } > >> > } > >> > } > >> > } > >> >