etch-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Paul Turner (JIRA)" <>
Subject [jira] [Commented] (ETCH-258) Switch to using util.concurrent instead of pre Java 5 threading constructs
Date Sat, 02 Mar 2013 21:51:13 GMT


Paul Turner commented on ETCH-258:

I have not changed things just to change them.  The changes I have made to convert to using
util.concurrent classes are mainly for reasons such as ability to recycle threads.

Motivation for change:
TodoManager is a threadpool with a capped queue capacity.  Methods to schedule the execution
of a Todo are synchronized,.
System performance will  degrade as too many requests are being created for  the threadpool
 and when it cannot service them.  This means that method calls will accumulate whilst waiting
for the instance scoped lock and will use memory beyond the capacity of the work queue.  In
effect, waiting synchronized method calls is a hidden and unbounded queue.

An approach used in the java.util.concurrent threadpool framework to deal with this degradation
is to force calling threads to carry out the execution of their own items scheduled on the
This is achieved by using a CallerRunsPolicy as the RejectedExecutionHandler in ThreadPoolExecutor.
This has 2 beneficial effects:
1: The producer threads ability to saturate the threadpool is limited because more more of
their time is spent servicing requests rather than producing them.
2: The amount of work to be done, saturation of threadpool and memory used in calls awaiting
instance lock is reduced.

I have changed the TodoManager class to use standard ExecutorService framework for the reasons
stated above.

Consequence of Change:
A feature of the original TodoManager is lost.  This is:
Ability to sleep while waiting for work queue capacity.  (As discussed previously)
This was configured by the entryDelay in the constructor of TodoManager.  The old constructor
remains for backwards-compatibility but is @Deprecated.
All public methods remain with the same contract.
Unit test added.

Motivation for change:
Adding alarms does not take advanatage of Java standard api classes.

I have changed the AlarmManager class to use a ScheduledExecutor.  All public methods remain
with the same contract.

Motivation for change:
Use standard Java apis for atomic incrementing number functionality

Instance level synchronization no longer necessary, An AtomicLong now takes care of atomic
incrementor functionality.  All public methods remain with the same contract.  Unit test added.

Motivation for change:
This is a threadpool and would benefit from the use of standard Java api classes.
Threadpool functionality now provided by Executors framework.  A SynchrouousQueue is used
to ensure a queue-free implementation rejecting runnables with an exception where necessary.
Overall effect is that threads are recycled by the threadpoolexecutor rather than being re-created
for each task.  All public methods remain with the same contract.

Motivation for change:
Unit tests were unpredictably failing due to a race condition in that the asynchronous PoolRunnable
execution may not have completed before the unit test Asserts are called.

The main thread of the unit test is now blocked by a CountDownLatch until all the asychronous
PoolRunnables complete.  I also added another test to make sure the SynchronousQueue used
as the threadpool BlockingQueue calles the RejectedExecutionHandler as expected. (Basically
a test for throwing an Exception when pool full -> probably a repeat of existing tests).

Remaining Work
I would like to make the Monitor support concurrent waitUntil* calls.  This is because the
current implementation blocks on e.g. waitUntilEq and it is not possible to lock acquire in
a fair way using the synchronized keyword.  Out of 2 synchronized calls to waitUntilEq one
will obtain the lock and the other will wait.  After the first method call has released the
lock a call to set() could be executed before the second call to waitUntilEq(...) obtains
the lock.  This means that  when the second call to waitUntilEq eventually acquires the lock
it could see a different value that was present when the method was invoked.  This is very
difficult because coordination between waitUntil*(...) and set(...) require the use of a lock
but once this lock has been acquired and the blocking call made to wait for changes, it is
not possible to release the lock to enable other calls to set(..) or waitUntil*(...).

A test case for this is as follows.

A monitor is set up with value = 1 and then to calls are made in separate threads to waitUntilEq.
 One waiting for 2, and later another waiting for 1.
Expected result: The call to waitUntilEq(2) will block indefinitely,  the call to waitUntilEq(1)
should return immediately.
Observed result: Both calls to waitUntilEq(...) block indefinitely.
I have added this test case to TestMonitor but without the @Test annotation so as not to affect
the build.

I would also like to refactor the CircularQueue to use a BlockingDeque as the internal double-ended
> Switch to using util.concurrent instead of pre Java 5 threading constructs
> --------------------------------------------------------------------------
>                 Key: ETCH-258
>                 URL:
>             Project: Etch
>          Issue Type: Improvement
>          Components: binding-java, general
>            Reporter: Paul Turner
>            Priority: Minor
>             Fix For: 1.4
>         Attachments: etch-20130301.patch
>   Original Estimate: 168h
>  Remaining Estimate: 168h
> thread creation is quite expensive and so a new thread per unit of work is also expensive,
i propose to use util.concurrent threadpools in the java binding sub-project and enhance unit
tests e.g. with countdown latches to ensure competing test threads start simeltanously and
semaphore to throttle access to running units of work.
> affects FreePool, TodoManager and associated tests and possibly more classes

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see:

View raw message