Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/utils/ExclusiveExec.java @ 782:725f7573b6ea
Added package description with text 'DOCUMENT ME!'.
gnv-artifacts/trunk@861 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 29 Mar 2010 10:28:32 +0000 |
parents | c4156275c1e1 |
children | 2cea76f1112e |
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(String)} 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(String)}. 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 { public static final ExclusiveExec INSTANCE = new ExclusiveExec(); private HashMap tokens; public static class UniqueKey { Object key; int [] refs; 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 :