[concurrency-interest] Questions on ConcurrentHashMap

Joe Bowbeer joe.bowbeer at gmail.com
Fri Nov 30 16:57:45 EST 2007


In the trace, the wait() inside create() was interrupted, not future.get().

I think you can "fix" the test by reasserting the interrupt in the
interrupt handler in the create() method.

On Nov 30, 2007 12:57 PM, Gregg Wonderly <gregg at cytetech.com> wrote:
> Tim Peierls wrote:
> > Sorry if this is obvious to everyone else, but I don't understand the
> > interrupt handling in the while loop. How does it terminate?
>
> On Windows xp SP2 with JDK 1.6, the following does run to completion.  The
> Thread.interrupt() does seem to raise some type of exceptional processing that
> the throws clause does not express...
>
> /**
>   * Thread-safe lock-less reference that is not constructed until required.
>   * <p>
>   * Implement create() in implementation.
>   */
> public abstract class LazyLoadedReference<V> {
>         private final AtomicReference<FutureTask<V>> ref = new
> AtomicReference<FutureTask<V>>();
>         Logger log = Logger.getLogger( getClass().getName() );
>         public final V get() {
>                 FutureTask<V> future = ref.get();
>                 if (future == null) {
>                         // create a Future
>                         future = new FutureTask<V>(new Callable<V>() {
>                                 public V call() throws Exception {
>                                         return create();
>                                 }
>                         });
>                         // set the reference only if it is still null
>                         ref.compareAndSet(null, future);
>                         // get the future that ref now holds (may be different to above
>                         future = ref.get();
>                 }
>                 try {
>                         while (true) {
>                                 try {
>                                         future.run();
>                                         return future.get();
>                                 } catch (InterruptedException ex) {
>                         //              log.log( Level.SEVERE, ex.toString()+": get Interrupted", ex );
>                                         Thread.currentThread().interrupt();
>                                 } catch (ExecutionException e) {
>                                         throw new RuntimeException(e);
>                                 }
>                         }
>                 } finally {
>                         log.info( "exiting get");
>                 }
>         }
>
>         /**
>          * The object factory method, guaranteed to be called once and only once.
>          */
>         protected abstract V create();
>
>         public static void main( String args[] ) throws InterruptedException {
>                 final Logger log = Logger.getLogger( LazyLoadedReference.class.getName() );
>
>                 final LazyLoadedReference<Integer> r = new LazyLoadedReference<Integer>() {
>                         protected Integer create() {
>                                 log.info("create called");
>                                 synchronized( this ) {
>                                         try {
>                                                 this.wait();
>                                         } catch (InterruptedException ex) {
>                                                 log.log( Level.SEVERE, ex.toString()+": wait was interrupted", ex );
>                                         }
>                                 }
>                                 return new Integer( 42 );
>                         }
>                 };
>
>                 Thread mt = new Thread() {
>                         public void run() {
>                                 log.info("creating");
>                                 try {
>                                         Integer v = r.get();
>                                         log.info("created: "+v);
>                                 } catch( Exception ex ) {
>                                         log.log( Level.SEVERE, ex.toString(), ex );
>                                 }
>                         }
>                 };
>                 log.info("running");
>                 mt.start();
>                 log.info("sleeping");
>                 Thread.currentThread().sleep(5000);
>                 log.info("interrupting");
>                 mt.interrupt();
>                 log.info("exiting");
>                 Object lock = new Object();
>                 synchronized(lock) {
>                         lock.wait();
>                 }
>         }
> }
>
> Here's the output I see...
>
> Nov 30, 2007 2:51:20 PM com.cytetech.util.LazyLoadedReference main
> INFO: running
> Nov 30, 2007 2:51:20 PM com.cytetech.util.LazyLoadedReference main
> INFO: sleeping
> Nov 30, 2007 2:51:20 PM com.cytetech.util.LazyLoadedReference$3 run
> INFO: creating
> Nov 30, 2007 2:51:20 PM com.cytetech.util.LazyLoadedReference$2 create
> INFO: create called
> Nov 30, 2007 2:51:25 PM com.cytetech.util.LazyLoadedReference main
> INFO: interrupting
> Nov 30, 2007 2:51:25 PM com.cytetech.util.LazyLoadedReference main
> INFO: exiting
> Nov 30, 2007 2:51:25 PM com.cytetech.util.LazyLoadedReference$2 create
> SEVERE: java.lang.InterruptedException: wait was interrupted
> java.lang.InterruptedException
>          at java.lang.Object.wait(Native Method)
>          at java.lang.Object.wait(Object.java:485)
>          at
> com.cytetech.util.LazyLoadedReference$2.create(LazyLoadedReference.java:71)
>          at
> com.cytetech.util.LazyLoadedReference$2.create(LazyLoadedReference.java:66)
>          at
> com.cytetech.util.LazyLoadedReference$1.call(LazyLoadedReference.java:33)
>          at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
>          at java.util.concurrent.FutureTask.run(FutureTask.java:138)
>          at com.cytetech.util.LazyLoadedReference.get(LazyLoadedReference.java:44)
>          at com.cytetech.util.LazyLoadedReference$3.run(LazyLoadedReference.java:84)
> Nov 30, 2007 2:51:25 PM com.cytetech.util.LazyLoadedReference get
> INFO: exiting get
> Nov 30, 2007 2:51:25 PM com.cytetech.util.LazyLoadedReference$3 run
> INFO: created: 42
>


More information about the Concurrency-interest mailing list