geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Jencks <david_jen...@yahoo.com>
Subject Re: Thread Pool Deadlock
Date Sun, 02 Sep 2007 16:46:54 GMT
I don't think the current implementation is actually wrong under  
normal use (where you just configure the gbean in xml and don't  
change its settings at runtime).

I think it would be better to set up the executor in its constructor  
(keeping the waitWhenBlocked as a constructor parameter).  There's a  
constructor for ThreadPoolExecutor we can use that lets us set  
everything at once.

I think the wait when blocked configuration is correct as it stands.   
I suggest that using the LinkedBlockingQueue is appropriate when  
waitWhenBlocked is false but not when its true.

IMO the caller-runs policy is not appropriate for use in j2ca since  
the work manager can notify you if the work is rejected.  Thus tying  
up your own thread is not appropriate since it eliminates the  
possibility of the caller taking corrective action.

thanks
david jencks

On Sep 2, 2007, at 8:46 AM, Manu George wrote:

> Hi,
>         I was investigating why setting the resourceAdapter poolsize
> to 1 and using it in an Mdb for sequential message processing was
> failing and found that the org.apache.geronimo.pool.ThreadPool class
> in geronimo contains a ThreadPoolExecutor instance created with the
> constructor
>
> new ThreadPoolExecutor(
>             poolSize, // core size
>             poolSize, // max size
>             keepAliveTime, TimeUnit.MILLISECONDS,
>             new SynchronousQueue());
>
> The default behaviour is to reject the Runnables supplied when the no
> of active threads equals the pool size.
>
> Now the ThreadPool class has a setWaitWhenBlocked method which when
> called makes it wait. Setting  this makes the pool enter into a
> deadlock. The reason for this is the WaitWhenBlockedPolicy used to
> process rejection. In this class there is a
> executor.getQueue().put(r);
> Now the API docs mention that once you handoff the queue to a
> ThreadPoolExecutor we should not directly modify the queue as it may
> result in unpredictable behaviour. So this is a bug.
>
> As a solution for this what I did was
>
>  ThreadPoolExecutor p = new ThreadPoolExecutor(
>             poolSize, // core size
>             poolSize, // max size
>             keepAliveTime, TimeUnit.MILLISECONDS,
>             new LinkedBlockingQueue<Runnable>(queueSize));
>
> Now this results in upto queue size of Runnables that can be submitted
> of which poolsize will be the no of parallel executions. More than
> queue size will be rejected.
> We can also set the rejection handler to the CallerRunsPolicy when the
> quesize is exceeded and the waitWhenBlocked flag is true.
>
> This results in me getting the scenario working. I am not yet sure why
> the SynchronousQueue was used in this case, so thats why I changed the
> queuing strategy. So Is this an acceptable approach for fixing this
> issue?
> Secondly do we want a behaviour of rejection of work items when queue
> is full? Setting the CallerRunsPolicy actually results in graceful
> degradation when load exceeds capacity by increasing backlog at the
> TCP/IP layer. Would be happy if some of the experts would comment on
> this
>
> Thanks
> Manu


Mime
View raw message