LockSupport併發等待基本模型。寫的個測試,具體請看註釋。
package test;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
/**
* @author Wei.Chou([email protected])
* @version 1.0, 12/08/2016
*/
public class ParkTest {
private static volatile boolean resulted;
private static volatile boolean completed;
private static volatile boolean end0;
private static volatile boolean end1;
private static final AtomicInteger parkCount = new AtomicInteger(0);
private static final Set<Thread> set = new CopyOnWriteArraySet<>();
private static volatile Object result;
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
int i = 0;
while (true) {
while (end0) Thread.yield();
System.out.println("thread started");
sync();
end0 = true;
System.out.println("thread end +++");
while (!end1) Thread.yield();
resulted = false;
completed = false;
System.out.println(">>>>>>>>>>>>>>>>>>>> thread +++ loop:" + i++ + ", parkCount:" + parkCount.get());
end1 = false;
}
}
}.start();
new Thread() {
@Override
public void run() {
int i = 0;
while (true) {
while (end1) Thread.yield();
System.out.println("thread1 started");
work();
end1 = true;
System.out.println("thread1 end ---");
while (!end0) Thread.yield();
System.out.println("<<<<<<<<<<<<<<<<<<<< thread1 --- loop:" + i++ + ", parkCount:" + parkCount.get());
set.clear();
end0 = false;
}
}
}.start();
}
private static Object sync() {
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread sync calling");
final Thread t = Thread.currentThread();
set.add(t);
if (Math.random() < .5) {
Thread.yield();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean unparked = false;
while (true) {
System.out.println("thread loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~-parkCount:"
+ parkCount.get());
if (completed) {
if (set.contains(t)) {
set.remove(t);
} else {
System.out.println("thread park ###########################-parkCount:"
+ parkCount.incrementAndGet());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// parkCount.incrementAndGet();
// 消化掉那個unpark
if (!unparked) LockSupport.park();
}
return result;
} else if (resulted) { // 走這個case是因爲很有可能在上面set.add(t)之前, 這個狀態就已經設置了。
// 那麼unpark()是在add(t)之前還是之後, 情況是隨機的, 無從知曉。
// 但又不能總yield(), 如果狀態沒有設置, 不知道要等多久, 那麼LockSupport.park()是最合適的。
//**********//
// 此時是個量子態,一切都不穩定,那就再來一遍。
// 但是這個狀態的持續時間極短暫,因此yield()是理想方法。
Thread.yield();
} else {
System.out.println("thread park ???????????????????????????-parkCount:"
+ parkCount.incrementAndGet());
// parkCount.incrementAndGet();
// 沒有得到結果,那就等着。
LockSupport.park();
// 保險起見, 再來一遍看看, 而不直接返回。
unparked = true;
}
}
}
private static void work() {
try {
System.out.println("thread1 working");
// work time
Thread.sleep((int) (Math.random() * 3000));
} catch (InterruptedException e) {
e.printStackTrace();
}
// 這裏只修改結果,完成的標識放最後
result = new Object();
System.out.println("thread1 resulted");
resulted = true;
for (Thread t : set) {
System.out.println("thread1 unpark---------------------------parkCount:"
+ parkCount.decrementAndGet());
// parkCount.decrementAndGet();
LockSupport.unpark(t);
set.remove(t);
}
System.out.println("thread1 completed");
completed = true;
}
}