在Java多線程情況下,線程之間可能存在執行的先後順序,那麼線程之間是如何實作通信的呢?
join()
當在一個線程中調用了另一個線程的join()方法時,目前線程将會挂起(不是自旋),直到目标線程執行結束。
public class JoinClass {
private class A extends Thread {
@Override
public void run() {
System.out.println("A");
}
}
private class B extends Thread {
private A a;
B(A a) {
this.a = a;
}
@Override
public void run() {
try {
a.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B");
}
}
public void test() {
A a = new A();
B b = new B(a);
b.start();
a.start();
}
}
public static void main(String[] args) {
JoinClass example = new JoinClass();
example.test();
}
輸出結果是
A
B
雖然是B線程先執行的,但因為在B線程中調用了a.join(),是以B線程會等待A線程執行完畢才會繼續執行。
wait() notify() notifyAll()
它們都屬于 Object 的方法,而不屬于 Thread。
當調用wait()方法時,線程會被挂起,等待條件滿足,當其他線程調用notify()(随機喚醒一個線程)、 notifyAll()(喚醒所有線程)時來喚醒被挂起的線程。
注意隻能用在同步方法或者同步控制塊中使用!否則會在運作時抛出 IllegalMonitorStateExeception。
**調用wait()方法時,線程會釋放鎖,這樣其他線程才能進入對象的同步代碼中調用對象的notify()方法喚醒線程。**如果沒有釋放鎖,将無法進入對象同步塊中調用notify() notifyAll()方法,造成死鎖。
public class WaitNotifyExample {
public synchronized void before() {
System.out.println("before");
notifyAll();
}
public synchronized void after() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after");
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
WaitNotifyExample example = new WaitNotifyExample();
executorService.execute(() -> example.after());
executorService.execute(() -> example.before());
}
執行結果是
before
after
await() signal() signalAll()
**java.util.concurrent 類庫中提供了 Condition 類來實作線程之間的協調,可以在 Condition 上調用 await() 方法使線程等待,其它線程調用 signal() 或 signalAll() 方法喚醒等待的線程。**相比于 wait() 這種等待方式,await() 可以指定等待的條件,是以更加靈活。
sleep和wait有什麼差別
- sleep() 是Thread類的靜态方法,wait()是Object類的方法。
- sleep() 不會釋放鎖(抱着鎖睡覺),休眠時間結束後自動恢複(回到就緒狀态)
- wait()會釋放鎖,當被notify() 方法(或 notifyAll() 方法)喚醒,如果線程重新獲得對象的鎖就可以進入就緒狀态。
原文:https://blog.csdn.net/Zhang_hongxin/article/details/82462267