原文地址:https://hexige.github.io/blog/2017/09/25/%E7%AD%89%E5%BE%85%E9%80%9A%E7%9F%A5%E6%9C%BA%E5%88%B6/
等待/通知機(jī)制
一個線程修改了一個對象的值,而另一個線程感知到了變化,然后進(jìn)行相應(yīng)的操作。前者為生產(chǎn)者,后者為消費(fèi)者。
消費(fèi)者:
- 獲取對象的鎖;
- 如果條件不滿足,調(diào)用對象的wait方法;
- 條件滿足則進(jìn)行對應(yīng)的操作;
sync(obj){
whlie(條件不滿足){
obj.wait();
}
對應(yīng)的操作;
}
生產(chǎn)者:
- 獲取對象的鎖;
- 改變條件;
- 通知所有等待在該對象上的線程;
sync(obj){
改變條件;
obj.notifyAll();
}
Thread.join()
Waits for this thread to die.
如果一個線程A執(zhí)行了threadB.join(),則表示線程A在threadB終止前一hang住,直到threadB終止,線程A才繼續(xù)執(zhí)行后續(xù)的操作;
public static void main(String[] args) {
Thread cur = Thread.currentThread();
for(int i =0;i<3;i++){
Thread thread = new Thread(new MRunaable(cur),String.valueOf(i));
thread.start();
cur = thread;
}
}
static class MRunaable implements Runnable{
private Thread preThread;
public MRunaable(Thread preThread) {
this.preThread = preThread;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
preThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
此時會按順序輸出線程名,即:等待前一個線程執(zhí)行完后,才執(zhí)行下面的輸出語句。若不使用preThread.join()方法,輸出的線程名不一定按照順序輸出。
join方法源碼:
public final void join(long millis) throws InterruptedException {
synchronized(lock) {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
lock.wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
lock.wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
}
join方法中的邏輯同等待/通知機(jī)制一致.
//條件不滿足,等待
while (isAlive()) {
lock.wait(0);
}
//滿足,方法返回