12 |
|
import java.util.Arrays; |
13 |
|
import java.util.Collection; |
14 |
|
import java.util.HashSet; |
15 |
+ |
import java.util.concurrent.Callable; |
16 |
|
import java.util.concurrent.CountDownLatch; |
17 |
|
import java.util.concurrent.CyclicBarrier; |
18 |
|
import java.util.concurrent.ThreadLocalRandom; |
19 |
+ |
import java.util.concurrent.atomic.AtomicBoolean; |
20 |
|
import java.util.concurrent.locks.Condition; |
21 |
+ |
import java.util.concurrent.locks.Lock; |
22 |
|
import java.util.concurrent.locks.ReentrantLock; |
23 |
|
|
24 |
|
import junit.framework.Test; |
1198 |
|
assertFalse(thread.isAlive()); |
1199 |
|
} |
1200 |
|
} |
1201 |
+ |
|
1202 |
+ |
/** |
1203 |
+ |
* ThreadMXBean reports the blockers that we expect. |
1204 |
+ |
*/ |
1205 |
+ |
public void testBlockers() { |
1206 |
+ |
if (!testImplementationDetails) return; |
1207 |
+ |
final boolean fair = randomBoolean(); |
1208 |
+ |
final boolean timedAcquire = randomBoolean(); |
1209 |
+ |
final boolean timedAwait = randomBoolean(); |
1210 |
+ |
final String syncClassName = fair |
1211 |
+ |
? "ReentrantLock$FairSync" |
1212 |
+ |
: "ReentrantLock$NonfairSync"; |
1213 |
+ |
final String conditionClassName |
1214 |
+ |
= "AbstractQueuedSynchronizer$ConditionObject"; |
1215 |
+ |
final Thread.State expectedAcquireState = timedAcquire |
1216 |
+ |
? Thread.State.TIMED_WAITING |
1217 |
+ |
: Thread.State.WAITING; |
1218 |
+ |
final Thread.State expectedAwaitState = timedAwait |
1219 |
+ |
? Thread.State.TIMED_WAITING |
1220 |
+ |
: Thread.State.WAITING; |
1221 |
+ |
final Lock lock = new ReentrantLock(fair); |
1222 |
+ |
final Condition condition = lock.newCondition(); |
1223 |
+ |
final AtomicBoolean conditionSatisfied = new AtomicBoolean(false); |
1224 |
+ |
lock.lock(); |
1225 |
+ |
final Thread thread = newStartedThread((Action) () -> { |
1226 |
+ |
if (timedAcquire) |
1227 |
+ |
lock.tryLock(LONGER_DELAY_MS, MILLISECONDS); |
1228 |
+ |
else |
1229 |
+ |
lock.lock(); |
1230 |
+ |
while (!conditionSatisfied.get()) |
1231 |
+ |
if (timedAwait) |
1232 |
+ |
condition.await(LONGER_DELAY_MS, MILLISECONDS); |
1233 |
+ |
else |
1234 |
+ |
condition.await(); |
1235 |
+ |
}); |
1236 |
+ |
Callable<Boolean> waitingForLock = () -> { |
1237 |
+ |
String className; |
1238 |
+ |
return thread.getState() == expectedAcquireState |
1239 |
+ |
&& (className = blockerClassName(thread)) != null |
1240 |
+ |
&& className.endsWith(syncClassName); |
1241 |
+ |
}; |
1242 |
+ |
waitForThreadToEnterWaitState(thread, waitingForLock); |
1243 |
+ |
|
1244 |
+ |
lock.unlock(); |
1245 |
+ |
Callable<Boolean> waitingForCondition = () -> { |
1246 |
+ |
String className; |
1247 |
+ |
return thread.getState() == expectedAwaitState |
1248 |
+ |
&& (className = blockerClassName(thread)) != null |
1249 |
+ |
&& className.endsWith(conditionClassName); |
1250 |
+ |
}; |
1251 |
+ |
waitForThreadToEnterWaitState(thread, waitingForCondition); |
1252 |
+ |
|
1253 |
+ |
// politely release the waiter |
1254 |
+ |
conditionSatisfied.set(true); |
1255 |
+ |
lock.lock(); |
1256 |
+ |
try { |
1257 |
+ |
condition.signal(); |
1258 |
+ |
} finally { lock.unlock(); } |
1259 |
+ |
|
1260 |
+ |
awaitTermination(thread); |
1261 |
+ |
} |
1262 |
|
} |