21
21
22
22
import java .util .concurrent .Semaphore ;
23
23
import java .util .concurrent .TimeUnit ;
24
- import java .util .concurrent .atomic .AtomicInteger ;
25
- import java .util .concurrent .locks .Lock ;
26
- import java .util .concurrent .locks .ReentrantLock ;
27
24
28
25
/**
29
26
* A fair limiter whose {@link #acquire} method is fair, i.e. the waiting threads are served in the order of arrival.
30
27
*/
31
28
public class FairLimiter implements Limiter {
32
29
private final int maxPermits ;
33
- /**
34
- * The lock used to protect @{link #acquireLocked}
35
- */
36
- private final Lock lock = new ReentrantLock (true );
37
30
private final Semaphore permits ;
38
31
39
32
/**
40
33
* The name of this limiter, used for metrics.
41
34
*/
42
35
private final String name ;
43
- /**
44
- * The number of threads waiting for permits, used for metrics.
45
- */
46
- private final AtomicInteger waitingThreads = new AtomicInteger (0 );
47
36
48
37
public FairLimiter (int size , String name ) {
49
38
this .maxPermits = size ;
50
- this .permits = new Semaphore (size );
39
+ this .permits = new Semaphore (size , true );
51
40
this .name = name ;
52
41
}
53
42
54
43
@ Override
55
44
public Handler acquire (int permit ) throws InterruptedException {
56
- waitingThreads .incrementAndGet ();
57
- try {
58
- return acquire0 (permit );
59
- } finally {
60
- waitingThreads .decrementAndGet ();
61
- }
62
- }
63
-
64
- private Handler acquire0 (int permit ) throws InterruptedException {
65
- lock .lock ();
66
- try {
67
- permits .acquire (permit );
68
- return new FairHandler (permit );
69
- } finally {
70
- lock .unlock ();
71
- }
45
+ permits .acquire (permit );
46
+ return new FairHandler (permit );
72
47
}
73
48
74
49
@ Override
75
50
public Handler acquire (int permit , long timeoutMs ) throws InterruptedException {
76
- waitingThreads .incrementAndGet ();
77
- try {
78
- return acquire0 (permit , timeoutMs );
79
- } finally {
80
- waitingThreads .decrementAndGet ();
81
- }
82
- }
83
-
84
- private Handler acquire0 (int permit , long timeoutMs ) throws InterruptedException {
85
- long start = System .nanoTime ();
86
- if (lock .tryLock (timeoutMs , TimeUnit .MILLISECONDS )) {
87
- try {
88
- // calculate the time left for {@code acquireLocked}
89
- long elapsed = System .nanoTime () - start ;
90
- long left = TimeUnit .MILLISECONDS .toNanos (timeoutMs ) - elapsed ;
91
- // note: {@code left} may be negative here, but it's OK for acquireLocked
92
- return acquireLocked (permit , left );
93
- } finally {
94
- lock .unlock ();
95
- }
96
- } else {
97
- // tryLock timeout, return null
98
- return null ;
99
- }
51
+ return acquireLocked (permit , timeoutMs );
100
52
}
101
53
102
54
@ Override
@@ -111,7 +63,7 @@ public int availablePermits() {
111
63
112
64
@ Override
113
65
public int waitingThreads () {
114
- return waitingThreads . get ();
66
+ return permits . getQueueLength ();
115
67
}
116
68
117
69
@ Override
0 commit comments