[concurrency-interest] Questions on ConcurrentHashMap

Gregg Wonderly gregg at cytetech.com
Fri Nov 30 15:57:54 EST 2007


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