| ||||
|
Code - Class EDU.oswego.cs.dl.util.concurrent.Semaphore1 /* 2 File: Semaphore.java 3 4 Originally written by Doug Lea and released into the public domain. 5 This may be used for any purposes whatsoever without acknowledgment. 6 Thanks for the assistance and support of Sun Microsystems Labs, 7 and everyone contributing, testing, and using this code. 8 9 History: 10 Date Who What 11 11Jun1998 dl Create public version 12 5Aug1998 dl replaced int counters with longs 13 24Aug1999 dl release(n): screen arguments 14 */ 15 16 package EDU.oswego.cs.dl.util.concurrent; 17 18 /** 19 * Base class for counting semaphores. 20 * Conceptually, a semaphore maintains a set of permits. 21 * Each acquire() blocks if necessary 22 * until a permit is available, and then takes it. 23 * Each release adds a permit. However, no actual permit objects 24 * are used; the Semaphore just keeps a count of the number 25 * available and acts accordingly. 26 * <p> 27 * A semaphore initialized to 1 can serve as a mutual exclusion 28 * lock. 29 * <p> 30 * Different implementation subclasses may provide different 31 * ordering guarantees (or lack thereof) surrounding which 32 * threads will be resumed upon a signal. 33 * <p> 34 * The default implementation makes NO 35 * guarantees about the order in which threads will 36 * acquire permits. It is often faster than other implementations. 37 * <p> 38 * <b>Sample usage.</b> Here is a class that uses a semaphore to 39 * help manage access to a pool of items. 40 * <pre> 41 * class Pool { 42 * static final MAX_AVAILABLE = 100; 43 * private final Semaphore available = new Semaphore(MAX_AVAILABLE); 44 * 45 * public Object getItem() throws InterruptedException { // no synch 46 * available.acquire(); 47 * return getNextAvailableItem(); 48 * } 49 * 50 * public void putItem(Object x) { // no synch 51 * if (markAsUnused(x)) 52 * available.release(); 53 * } 54 * 55 * // Not a particularly efficient data structure; just for demo 56 * 57 * protected Object[] items = ... whatever kinds of items being managed 58 * protected boolean[] used = new boolean[MAX_AVAILABLE]; 59 * 60 * protected synchronized Object getNextAvailableItem() { 61 * for (int i = 0; i < MAX_AVAILABLE; ++i) { 62 * if (!used[i]) { 63 * used[i] = true; 64 * return items[i]; 65 * } 66 * } 67 * return null; // not reached 68 * } 69 * 70 * protected synchronized boolean markAsUnused(Object item) { 71 * for (int i = 0; i < MAX_AVAILABLE; ++i) { 72 * if (item == items[i]) { 73 * if (used[i]) { 74 * used[i] = false; 75 * return true; 76 * } 77 * else 78 * return false; 79 * } 80 * } 81 * return false; 82 * } 83 * 84 * } 85 *</pre> 86 * <p>[<a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] 87 **/ 88 89 90 public class Semaphore implements Sync { 91 /** current number of available permits **/ 92 protected long permits_; 93 94 /** 95 * Create a Semaphore with the given initial number of permits. 96 * Using a seed of one makes the semaphore act as a mutual exclusion lock. 97 * Negative seeds are also allowed, in which case no acquires will proceed 98 * until the number of releases has pushed the number of permits past 0. 99 **/ 100 public Semaphore(long initialPermits) { permits_ = initialPermits; } 101 102 103 /** Wait until a permit is available, and take one **/ 104 public void acquire() throws InterruptedException { 105 if (Thread.interrupted()) throw new InterruptedException(); 106 synchronized(this) { 107 try { 108 while (permits_ <= 0) wait(); 109 --permits_; 110 } 111 catch (InterruptedException ex) { 112 notify(); 113 throw ex; 114 } 115 } 116 } 117 118 /** Wait at most msecs millisconds for a permit. **/ 119 public boolean attempt(long msecs) throws InterruptedException { 120 if (Thread.interrupted()) throw new InterruptedException(); 121 122 synchronized(this) { 123 if (permits_ > 0) { 124 --permits_; 125 return true; 126 } 127 else if (msecs <= 0) 128 return false; 129 else { 130 try { 131 long startTime = System.currentTimeMillis(); 132 long waitTime = msecs; 133 134 for (;;) { 135 wait(waitTime); 136 if (permits_ > 0) { 137 --permits_; 138 return true; 139 } 140 else { 141 waitTime = msecs - (System.currentTimeMillis() - startTime); 142 if (waitTime <= 0) 143 return false; 144 } 145 } 146 } 147 catch(InterruptedException ex) { 148 notify(); 149 throw ex; 150 } 151 } 152 } 153 } 154 155 /** Release a permit **/ 156 public synchronized void release() { 157 ++permits_; 158 notify(); 159 } 160 161 162 /** 163 * Release N permits. <code>release(n)</code> is 164 * equivalent in effect to: 165 * <pre> 166 * for (int i = 0; i < n; ++i) release(); 167 * </pre> 168 * <p> 169 * But may be more efficient in some semaphore implementations. 170 * @exception IllegalArgumentException if n is negative. 171 **/ 172 public synchronized void release(long n) { 173 if (n < 0) throw new IllegalArgumentException("Negative argument"); 174 175 permits_ += n; 176 for (long i = 0; i < n; ++i) notify(); 177 } 178 179 /** 180 * Return the current number of available permits. 181 * Returns an accurate, but possibly unstable value, 182 * that may change immediately after returning. 183 **/ 184 public synchronized long permits() { 185 return permits_; 186 } 187 188 } 189 190 |
|||
Java API By Example, From Geeks To Geeks. |
Conditions of Use |
About Us
© 2002 - 2005, KickJava.com, or its affiliates
|