多线程停车位实例多线程停车位实例 本文将介绍用来控制资源同时访问个数的Semaphore工具类, 然后采用 Semaphore给出一个泊车的实例,最后给出Semaphore和CountDownLatch的几点 比较. 1. Semaphore工具类介绍 Java代码 1. /** 2. * A counting semaphore. Conceptually, a semaphore maintains a set of 3. * permits. Each {@link #acquire} blocks if ne...
Semaphores are often used to restrict the number of threa9. * ds than can 10. * access some (physical or logical) resource. 11. */ 从Semaphore的注释中可以看出如下几点: 1.从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一 个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能 释放一个正在阻塞的获取者。 2. Semaphore并不使用实际的许可对象,Semaphore 只对可用许可进行计数, 并采取相应的行动。 3.Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。 Semaphore中定义了一个内部类Sync,该类继承AbstractQueuedSynchronizer。 从代码中可以看出,Semaphore的 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 基本上都调用了Sync的方法来实现。 Smaphore还提供了公平和非公平的两种方式. Semaphore工具类相关的类图以及详细代码如下: Java代码 1. /* * @(#)Semaphore.java 1.8 04/07/12 2. 3. * 4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license term s. 6. */ 7. 8. package java.util.concurrent; 9. import java.util.*; 10.import java.util.concurrent.locks.*; 11.import java.util.concurrent.atomic.*; 12. 13./** 14. * A counting semaphore. Conceptually, a semaphore maintains a set of 15. * permits. Each {@link #acquire} blocks if necessary until a permit is 16. * available, and then takes it. Each {@link #release} adds a permit, 17. * potentially releasing a blocking acquirer. 18. * However, no actual permit objects are used; the Semaphor e just * 19.keeps a count of the number available and acts accordingly. 20. * 21. *
Semaphores are often used to restrict the number of threa ds than can 22. * access some (physical or logical) resource. For example, her e is 23. * a class that uses a semaphore to control access to a pool of items: 24. *
25. * class Pool { 26. * private static final MAX_AVAILABLE = 100; 27. * private final Semaphore available = new Semaphore(MAX_AVAI LABLE, true); 28. * 29. * public Object getItem() throws InterruptedException { 30. * available.acquire(); 31. * return getNextAvailableItem(); 32. * } 33. * 34. * public void putItem(Object x) { 35. * if (markAsUnused(x)) 36. * available.release(); 37. * } 38. * 39. * // Not a particularly efficient data structure; just for d emo 40. * 41. * protected Object[] items = ... whatever kinds of items bei ng managed 42. * protected boolean[] used = new boolean[MAX_AVAILABLE]; 43. * 44. * protected synchronized Object getNextAvailableItem() { 45. * for (int i = 0; i < MAX_AVAILABLE; ++i) { 46. * if (!used[i]) { 47. * used[i] = true; 48. * return items[i]; 49. * } 50. * } 51. * return null; // not reached 52. * } 53. * 54. * protected synchronized boolean markAsUnused(Object item) { 55. * for (int i = 0; i < MAX_AVAILABLE; ++i) { 56. * if (item == items[i]) { 57. * if (used[i]) { 58. * used[i] = false; 59. * return true; 60. * } else 61. * return false; 62. * } } 63. * 64. * return false; 65. * } 66. * 67. * } 68. *69. * 70. *
Before obtaining an item each thread must acquire a permi t from 71. * the semaphore, guaranteeing that an item is available for us e. When 72. * the thread has finished with the item it is returned back to the 73. * pool and a permit is returned to the semaphore, allowing ano ther 74. * thread to acquire that item. Note that no synchronization l ock is 75. * held when {@link #acquire} is called as that would prevent a n item 76. * from being returned to the pool. The semaphore encapsulates the 77. * synchronization needed to restrict access to the pool, separ ately 78. * from any synchronization needed to maintain the consistency of the 79. * pool itself. 80. * 81. *
A semaphore initialized to one, and which is used such th at it 82. * only has at most one permit available, can serve as a mutual 83. * exclusion lock. This is more commonly known as a [i]binary 84. * semaphore[/i], because it only has two states: one permit 85. * available, or zero permits available. When used in this way , the 86. * binary semaphore has the property (unlike many {@link Lock} 87. * implementations), that the "lock" can be released by a 88. * thread other than the owner (as semaphores have no notion of 89. * ownership). This can be useful in some specialized contexts , such 90. * as deadlock recovery. 91. * 92. *
The constructor for this class optionally accepts a [i]fairness[/i] parameter. When set false, this class makes 93. * no 94. * guarantees about the order in which threads acquire permits. In 95. * particular, [i]barging[/i] is permitted, that is, a thread 96. * invoking {@link #acquire} can be allocated a permit ahead of a 97. * thread that has been waiting - logically the new thread plac es itself at 98. * the head of the queue of waiting threads. When fairness is s et true, the 99. * semaphore guarantees that threads invoking any of the {@link 100. * #acquire() acquire} methods are selected to obtain perm its in the order in 101. * which their invocation of those methods was processed 102. * (first-in-first-out; FIFO). Note that FIFO ordering nec essarily 103. * applies to specific internal points of execution within these 104. * methods. So, it is possible for one thread to invoke 105. * acquire before another, but reach the ordering point after 106. * the other, and similarly upon return from the method. 107. * Also note that the untimed {@link #tryAcquire() tryAcqu ire} methods do not 108. * honor the fairness setting, but will take any permits t hat are 109. * available. 110. * 111. *
Generally, semaphores used to control resource acces s should be 112. * initialized as fair, to ensure that no thread is starve d out from 113. * accessing a resource. When using semaphores for other k inds of 114. * synchronization control, the throughput advantages of n on-fair 115. * ordering often outweigh fairness considerations. 116. * 117. *
This class also provides convenience methods to {@li nk 118. * #acquire(int) acquire} and {@link #release(int) release } multiple 119. * permits at a time. Beware of the increased risk of ind efinite 120. * postponement when these methods are used without fairne ss set true. 121. * 122. * @since 1.5 123. * @author Doug Lea 124. * 125. */ 126. 127. public class Semaphore implements java.io.Serializable { 128. private static final long serialVersionUID = -32225786 61600680210L; 129. /** All mechanics via AbstractQueuedSynchronizer subcl ass */ 130. private final Sync sync; 131. 132. /** 133. * Synchronization implementation for semaphore. Uses AQS state 134. * to represent permits. Subclassed into fair and nonf air 135. * versions. 136. */ 137. abstract static class Sync extends AbstractQueuedSynch ronizer { 138. Sync(int permits) { 139. setState(permits); 140. } 141. 142. final int getPermits() { 143. return getState(); 144. } 145. 146. final int nonfairTryAcquireShared(int acquires) { 147. for (;;) { 148. int available = getState(); 149. int remaining = available - acquires; 150. if (remaining < 0 || 151. compareAndSetState(available, remainin g)) 152. return remaining; } 153. 154. } 155. 156. protected final boolean tryReleaseShared(int relea ses) { 157. for (;;) { 158. int p = getState(); 159. if (compareAndSetState(p, p + releases)) 160. return true; 161. } 162. } 163. 164. final void reducePermits(int reductions) { 165. for (;;) { 166. int current = getState(); 167. int next = current - reductions; 168. if (compareAndSetState(current, next)) 169. return; 170. } 171. } 172. 173. final int drainPermits() { 174. for (;;) { 175. int current = getState(); 176. if (current == 0 || compareAndSetState(cur rent, 0)) 177. return current; 178. } 179. } 180. } 181. 182. /** 183. * NonFair version 184. */ 185. final static class NonfairSync extends Sync { 186. NonfairSync(int permits) { 187. super(permits); 188. } 189. 190. protected int tryAcquireShared(int acquires) { 191. return nonfairTryAcquireShared(acquires); 192. } 193. } 194. 195. /** 196. * Fair version 197. */ 198. final static class FairSync extends Sync { 199. FairSync(int permits) { 200. super(permits); 201. } 202. 203. protected int tryAcquireShared(int acquires) { 204. Thread current = Thread.currentThread(); 205. for (;;) { 206. Thread first = getFirstQueuedThread(); 207. if (first != null && first != current) 208. return -1; 209. int available = getState(); 210. int remaining = available - acquires; 211. if (remaining < 0 || 212. compareAndSetState(available, remainin g)) 213. return remaining; 214. } 215. } 216. } 217. 218. /** 219. * Creates a Semaphore with the given number of 220. * permits and nonfair fairness setting. 221. * @param permits the initial number of permits availa ble. This 222. * value may be negative, in which case releases must 223. * occur before any acquires will be granted. 224. */ 225. public Semaphore(int permits) { 226. sync = new NonfairSync(permits); 227. } 228. 229. /** 230. * Creates a Semaphore with the given number of 231. * permits and the given fairness setting. 232. * @param permits the initial number of permits availa ble. This * value may be negative, in which case releases must 233. 234. * occur before any acquires will be granted. 235. * @param fair true if this semaphore will guarantee f irst-in 236. * first-out granting of permits under contention, els e false. 237. */ 238. public Semaphore(int permits, boolean fair) { 239. sync = (fair)? new FairSync(permits) : new Nonfair Sync(permits); 240. } 241. 242. /** 243. * Acquires a permit from this semaphore, blocking unt il one is 244. * available, or the thread is {@link Thread#interrupt interrupted}. 245. * 246. *
Acquires a permit, if one is available and retur ns immediately, 247. * reducing the number of available permits by one. 248. *
If no permit is available then the current threa d becomes 249. * disabled for thread scheduling purposes and lies do rmant until 250. * one of two things happens: 251. * [list] 252. *
If the current thread: 259. * [list] 260. *
Acquires a permit, if one is available and retur ns immediately, 280. * reducing the number of available permits by one. 281. *
If no permit is available then the current threa d becomes 282. * disabled for thread scheduling purposes and lies do rmant until 283. * some other thread invokes the {@link #release} meth od for this 284. * semaphore and the current thread is next to be assi gned a permit. 285. * 286. *
If the current thread 287. * is {@link Thread#interrupt interrupted} while waiti ng 288. * for a permit then it will continue to wait, but the time at which 289. * the thread is assigned a permit may change compared to the time it 290. * would have received the permit had no interruption occurred. When the 291. * thread does return from this method its interrupt s tatus will be set. 292. * 293. */ 294. public void acquireUninterruptibly() { sync.acquireShared(1); 295. 296. } 297. 298. /** 299. * Acquires a permit from this semaphore, only if one is available at the 300. * time of invocation. 301. *
Acquires a permit, if one is available and retur ns immediately, 302. * with the value true, 303. * reducing the number of available permits by one. 304. * 305. *
If no permit is available then this method will return 306. * immediately with the value false. 307. * 308. *
Even when this semaphore has been set to use a 309. * fair ordering policy, a call to tryAcquire() [i]will[/i] 310. * immediately acquire a permit if one is available, w hether or not 311. * other threads are currently waiting. 312. * This "barging" behavior can be useful in certain 313. * circumstances, even though it breaks fairness. If y ou want to honor 314. * the fairness setting, then use 315. * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, Ti meUnit.SECONDS) } 316. * which is almost equivalent (it also detects interru ption). 317. * 318. * @return true if a permit was acquired and false 319. * otherwise. 320. */ 321. public boolean tryAcquire() { 322. return sync.nonfairTryAcquireShared(1) >= 0; 323. } 324. 325. /** 326. * Acquires a permit from this semaphore, if one becom es available 327. * within the given waiting time and the 328. * current thread has not been {@link Thread#interrupt interrupted}. 329. *
Acquires a permit, if one is available and retur ns immediately, 330. * with the value true, 331. * reducing the number of available permits by one. 332. *
If no permit is available then 333. * the current thread becomes disabled for thread sche duling 334. * purposes and lies dormant until one of three things happens: 335. * [list] 336. *
If a permit is acquired then the value true< /tt> is returned. 343. *
If the current thread: 344. * [list] 345. *
If the specified waiting time elapses then the v alue false 352. * is returned. 353. * If the time is less than or equal to zero, the meth od will not wait 354. * at all. 355. * 356. * @param timeout the maximum time to wait for a permi t 357. * @param unit the time unit of the timeout a rgument. 358. * @return true if a permit was acquired and false 359. * if the waiting time elapsed before a permit was acq uired. 360. * 361. * @throws InterruptedException if the current thread is interrupted 362. * 363. * @see Thread#interrupt 364. * 365. */ 366. public boolean tryAcquire(long timeout, TimeUnit unit) 367. throws InterruptedException { 368. return sync.tryAcquireSharedNanos(1, unit.toNanos( timeout)); 369. } 370. 371. /** 372. * Releases a permit, returning it to the semaphore. 373. *
Releases a permit, increasing the number of avai lable permits 374. * by one. 375. * If any threads are trying to acquire a permit, then one 376. * is selected and given the permit that was just rele ased. 377. * That thread is (re)enabled for thread scheduling pu rposes. 378. *
There is no requirement that a thread that relea ses a permit must 379. * have acquired that permit by calling {@link #acquir e}. 380. * Correct usage of a semaphore is established by prog ramming convention 381. * in the application. 382. */ 383. public void release() { 384. sync.releaseShared(1); 385. } 386. 387. /** * Acquires the given number of permits from this sema388. phore, 389. * blocking until all are available, 390. * or the thread is {@link Thread#interrupt interrupte d}. 391. * 392. *
Acquires the given number of permits, if they ar e available, 393. * and returns immediately, 394. * reducing the number of available permits by the giv en amount. 395. * 396. *
If insufficient permits are available then the c urrent thread becomes 397. * disabled for thread scheduling purposes and lies do rmant until 398. * one of two things happens: 399. * [list] 400. *
If the current thread: 408. * [list] 409. *
Acquires the given number of permits, if they ar e available, 436. * and returns immediately, 437. * reducing the number of available permits by the giv en amount. 438. * 439. *
If insufficient permits are available then the c urrent thread becomes 440. * disabled for thread scheduling purposes and lies do rmant until 441. * some other thread invokes one of the {@link #releas e() release} 442. * methods for this semaphore, the current thread is n ext to be assigned 443. * permits and the number of available permits satisfi es this request. 444. * 445. *
If the current thread 446. * is {@link Thread#interrupt interrupted} while waiti ng 447. * for permits then it will continue to wait and its p osition in the 448. * queue is not affected. When the 449. * thread does return from this method its interrupt s tatus will be set. 450. * 451. * @param permits the number of permits to acquire 452. * @throws IllegalArgumentException if permits less th an zero. 453. * 454. */ 455. public void acquireUninterruptibly(int permits) { 456. if (permits < 0) throw new IllegalArgumentExceptio n(); 457. sync.acquireShared(permits); 458. } 459. 460. /** 461. * Acquires the given number of permits from this sema phore, only 462. * if all are available at the time of invocation. 463. * 464. *
Acquires the given number of permits, if they ar e available, and 465. * returns immediately, with the value true, 466. * reducing the number of available permits by the giv en amount. 467. * 468. *
If insufficient permits are available then this method will return 469. * immediately with the value false and the n umber of available 470. * permits is unchanged. 471. * 472. *
Even when this semaphore has been set to use a f air ordering 473. * policy, a call to tryAcquire [i]will[/i] 474. * immediately acquire a permit if one is available, w hether or 475. * not other threads are currently waiting. This 476. * "barging" behavior can be useful in certain 477. * circumstances, even though it breaks fairness. If y ou want to * honor the fairness setting, then use {@link #tryAcq478. uire(int, 479. * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SEC ONDS) } 480. * which is almost equivalent (it also detects interru ption). 481. * 482. * @param permits the number of permits to acquire 483. * 484. * @return true if the permits were acquired and false 485. * otherwise. 486. * @throws IllegalArgumentException if permits less th an zero. 487. */ 488. public boolean tryAcquire(int permits) { 489. if (permits < 0) throw new IllegalArgumentExceptio n(); 490. return sync.nonfairTryAcquireShared(permits) >= 0; 491. } 492. 493. /** 494. * Acquires the given number of permits from this sema phore, if all 495. * become available within the given waiting time and the 496. * current thread has not been {@link Thread#interrupt interrupted}. 497. *
Acquires the given number of permits, if they ar e available and 498. * returns immediately, with the value true, 499. * reducing the number of available permits by the giv en amount. 500. *
If insufficient permits are available then 501. * the current thread becomes disabled for thread sche duling 502. * purposes and lies dormant until one of three things happens: 503. * [list] 504. *
If the permits are acquired then the value t rue is returned. 512. *
If the current thread: 513. * [list] 514. *
If the specified waiting time elapses then the v alue false 525. * is returned. 526. * If the time is 527. * less than or equal to zero, the method will not wai t at all. 528. * Any permits that were to be assigned to this thread , are instead 529. * assigned to other threads trying to acquire permits , as if 530. * the permits had been made available by a call to {@ link #release()}. 531. * 532. * @param permits the number of permits to acquire 533. * @param timeout the maximum time to wait for the per mits * @param unit the time unit of the timeout a534. rgument. 535. * @return true if all permits were acquired and false 536. * if the waiting time elapsed before all permits were acquired. 537. * 538. * @throws InterruptedException if the current thread is interrupted 539. * @throws IllegalArgumentException if permits less th an zero. 540. * 541. * @see Thread#interrupt 542. * 543. */ 544. public boolean tryAcquire(int permits, long timeout, T imeUnit unit) 545. throws InterruptedException { 546. if (permits < 0) throw new IllegalArgumentExceptio n(); 547. return sync.tryAcquireSharedNanos(permits, unit.to Nanos(timeout)); 548. } 549. 550. /** 551. * Releases the given number of permits, returning the m to the semaphore. 552. *
Releases the given number of permits, increasing the number of 553. * available permits by that amount. 554. * If any threads are trying to acquire permits, then one 555. * is selected and given the permits that were just re leased. 556. * If the number of available permits satisfies that t hread's request 557. * then that thread is (re)enabled for thread scheduli ng purposes; 558. * otherwise the thread will wait until sufficient per mits are available. 559. * If there are still permits available 560. * after this thread's request has been satisfied, the n those permits 561. * are assigned in turn to other threads trying to acq uire permits. 562. * 563. *
There is no requirement that a thread that relea ses a permit must 564. * have acquired that permit by calling {@link Semapho re#acquire acquire}. 565. * Correct usage of a semaphore is established by prog ramming convention 566. * in the application. 567. * 568. * @param permits the number of permits to release 569. * @throws IllegalArgumentException if permits less th an zero. 570. */ 571. public void release(int permits) { 572. if (permits < 0) throw new IllegalArgumentExceptio n(); 573. sync.releaseShared(permits); 574. } 575. 576. /** 577. * Returns the current number of permits available in this semaphore. 578. *
This method is typically used for debugging and
testing purposes.
579. * @return the number of permits available in this sem
aphore.
580. */
581. public int availablePermits() {
582. return sync.getPermits();
583. }
584.
585. /**
586. * Acquire and return all permits that are immediately
available.
587. * @return the number of permits
588. */
589. public int drainPermits() {
590. return sync.drainPermits();
591. }
592.
593. /**
594. * Shrinks the number of available permits by the indi
cated
* reduction. This method can be useful in subclasses 595.
that use
596. * semaphores to track resources that become unavailab
le. This
597. * method differs from acquire in that it doe
s not block
598. * waiting for permits to become available. 599. * @param reduction the number of permits to remove 600. * @throws IllegalArgumentException if reduction is ne
gative
601. */
602. protected void reducePermits(int reduction) { 603. if (reduction < 0) throw new IllegalArgumentException(
);
604. sync.reducePermits(reduction);
605. }
606.
607. /**
608. * Returns true if this semaphore has fairness set tru
e.
609. * @return true if this semaphore has fairness set tru
e.
610. */
611. public boolean isFair() {
612. return sync instanceof FairSync;
613. }
614.
615. /**
616. * Queries whether any threads are waiting to acquire.
Note that
617. * because cancellations may occur at any time, a
true
618. * return does not guarantee that any other thread wil
l ever
619. * acquire. This method is designed primarily for use
in
620. * monitoring of the system state.
621. *
622. * @return true if there may be other threads waiting
to acquire
623. * the lock.
624. */
625. public final boolean hasQueuedThreads() { 626. return sync.hasQueuedThreads();
} 627.
628.
629. /**
630. * Returns an estimate of the number of threads waitin
g to
631. * acquire. The value is only an estimate because the
number of
632. * threads may change dynamically while this method tr
averses
633. * internal data structures. This method is designed
for use in
634. * monitoring of the system state, not for synchroniza
tion
635. * control.
636. * @return the estimated number of threads waiting for
this lock
637. */
638. public final int getQueueLength() {
639. return sync.getQueueLength();
640. }
641.
642. /**
643. * Returns a collection containing threads that may be
waiting to
644. * acquire. Because the actual set of threads may cha
nge
645. * dynamically while constructing this result, the ret
urned
646. * collection is only a best-effort estimate. The ele
ments of the
647. * returned collection are in no particular order. Th
is method is
648. * designed to facilitate construction of subclasses t
hat provide
649. * more extensive monitoring facilities. 650. * @return the collection of threads
651. */
652. protected Collection