Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/utils/ExclusiveExec.java @ 1113:e7efbded1367
Summarized changes for RELEASE 1.1
gnv-artifacts/trunk@1251 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Wed, 30 Jun 2010 12:26:04 +0000 |
parents | 22c18083225e |
children | f953c9a559d8 |
line wrap: on
line source
package de.intevation.gnv.utils; import java.util.HashMap; /** * This class can be used to synchronize threads with a given key. To use this * synchronization, you first need to do call {@link #acquire(java.lang.Object)} * to retrieve a {@link UniqueKey}. After this, you can call the code being * synchronized. After this execution, you need to call * {@link #release(UniqueKey)} with your token you retrieved from {@link * #acquire(java.lang.Object)}. A thread needs to wait for another thread if their keys * are equal. Threads with different keys don't need to wait for each other. * * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public final class ExclusiveExec { /** * The only instance of this singleton. */ public static final ExclusiveExec INSTANCE = new ExclusiveExec(); private HashMap tokens; /** * This class represents a unique key with a reference counter. */ public static class UniqueKey { Object key; int [] refs; /** * Constructs a new UniqueKey. * * @param key The key of this unique key. */ public UniqueKey(Object key) { this.key = key; refs = new int[1]; } } /** * Private constructor. Use {@link #INSTANCE} instead. */ private ExclusiveExec() { tokens = new HashMap(); } /** * This method serves a {@link UniqueKey} and starts a synchronized code * block. * * @param key The key used to identify same threads. * @return UniqueKey. Use this object to call {@link #release(UniqueKey)} * at the end of your code being synchronized. */ public UniqueKey acquire(Object key) { try { UniqueKey internalKey = null; synchronized (tokens) { internalKey = (UniqueKey)tokens.get(key); if (internalKey == null) { tokens.put(key, internalKey = new UniqueKey(key)); } } synchronized (internalKey) { ++internalKey.refs[0]; while (internalKey.refs[0] > 1) { internalKey.wait(10000L); } } return internalKey; } catch (InterruptedException ie) { return null; } } /** * This method releases a lock. Call this method at the end of your code * being synchronized. * * @param internalKey Token retrieved by {@link #acquire(Object)}. */ public void release(UniqueKey internalKey) { if (internalKey != null) { synchronized (internalKey) { if (--internalKey.refs[0] < 1) { synchronized (tokens) { tokens.remove(internalKey.key); } } internalKey.notifyAll(); } } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :