目錄
一、整體圖表
二、補充知識
下圖取之Java線程狀態
如上圖所示:
- 總共分爲六個狀態(運行態和就緒態歸爲運行態)
三、具體方法
3.1 wait方法
3.1.1定義
讓線程進入等待並且釋放鎖。
3.1.2注意
- 當前線程必須持有該對象的鎖
wait
必須被喚醒後或者設置時間進入隊列才能繼續執行接下來的操作
3.1.3使用方式
public static Object object = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Thread1());
thread3.start();
}
static class Thread1 implements Runnable {
@Override
public void run() {
//比如在同步代碼塊或者方法裏且得到該對象的鎖
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " is running.");
try {
//對象進入等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " get the lock.");
}
}
}
3.2 notify方法
3.2.1定義
喚醒任意一個等待的線程。
3.2.2注意
- 當前線程必須持有該對象的鎖
notify
後會喚醒一個正在等待的線程- 但是當前線程不會馬上放棄鎖的持有權,而是在同步代碼執行完畢後纔會釋放鎖
3.2.3 使用方式
//步驟
//1.先讓線程0執行然後進行等待
//2.再讓線程1執行然後通過 notify 喚醒0線程(因爲等待隊列只有0線程)
//3.線程1執行結束後會執行線程0
public static Object object = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Thread1());
Thread thread2 = new Thread(new Thread2());
thread1.start();
Thread.sleep(1000);
thread2.start();
}
static class Thread1 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " running.");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " get the lock.");
}
}
}
static class Thread2 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " is running.");
object.notify();
System.out.println(Thread.currentThread().getName() + " invoke notify()");
System.out.println(Thread.currentThread().getName() + " release the lock.");
}
}
}
//結果:
Thread-0 running.
Thread-1 is running.
Thread-1 invoke notify()
Thread-1 release the lock.
Thread-0 get the lock.
3.3 notifyAll
3.3.1定義
喚醒所有在等待的鎖。
3.3.2注意
- 當前線程必須持有該對象的鎖
notify
後會喚醒所有在等待的鎖- 但是當前線程不會馬上放棄鎖的持有權,而是在同步代碼執行完畢後纔會釋放鎖
3.3.3 使用方式
步驟
- 先讓線程0以及線程1執行然後進行等待
- 再讓線程2執行然後通過
notifyAll
喚醒所有線程並進入終止狀態(TERMINATED
) - 線程0,1從等待狀態(
WAITING
)進入阻塞(BLOCKED
)狀態 - 線程1獲得鎖進入運行狀態(
RUNNABLE
) - 之後線程1進入終止狀態(
TERMINATED
),線程0進入運行狀態(RUNNABLE
),之後終止(TERMINATED
)
執行順序:
public static Object object = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Thread1());
Thread thread2 = new Thread(new Thread2());
Thread thread3 = new Thread(new Thread3());
thread1.start();
thread2.start();
Thread.sleep(1000);
thread3.start();
}
static class Thread1 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " running.");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " get the lock.");
}
}
}
static class Thread2 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " running.");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " get the lock.");
}
}
}
static class Thread3 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " is running.");
object.notifyAll();
System.out.println(Thread.currentThread().getName() + " invoke notifyAll()");
System.out.println(Thread.currentThread().getName() + " release the lock.");
}
}
}
結果:
Thread-0 running.
Thread-1 running.
Thread-2 is running.
Thread-2 invoke notifyAll()
Thread-2 release the lock.
Thread-1 get the lock.
Thread-0 get the lock.