之前在單例模式時有提過,使用懶漢式 的方式在定義單例模式時,有可能會發生線程不安全的問題。
class Bank {
private static Bank instance;
private Bank() {}
public static Bank getInstance() {
synchronized(Bank.class) {
if(instance == null) {
instance = new Bank();
}
return instance;
}
}
}
透過synchronized 可以避免發生多個線程時,創建了兩個Bank 的實例。
線程間的通信指的是,當不同的線程需要共同完成某一項任務時,透過通信的方式,讓他們能夠按照規律的方式執行,而不會產生非預期的狀況發生。
可以透過等待 、喚醒 、喚醒全部 三個方法去進行這樣的操作
wait() :當線程執行到wait() 時,會進入等待狀態,並且將鎖 釋放。notify() :當線程執行到notify() 時,會喚醒等待 狀態中優先級最高的線程,若優先級相同會隨機喚醒其中一個線程,被喚醒 的線程會從進入等待狀態時的程式碼繼續執行。notifyAll() :當線程執行到notifyAll() 時會喚醒所有等待 狀態中的線程。// 要使用兩個線程交互印出1-100的數字
class PrintNumber implements Runnable {
private int number = 1;
@Override
public void run() {
synchronized(this) {
// 須注意必須和鎖為同一個物件
this.notify();
while(true) {
if(number <= 100) {
System.out.println(Thread.currentThread().getName() + ":" + i);
number++;
} else {
break;
}
try {
// 須注意必須和鎖為同一個物件
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
使用這三個方法時需要注意幾個點
synchronized 方法或同步塊中使用。synchronized 使用的鎖為同一個 物件,若不相同會有IllegalMonitorStateException 異常。Object 類中。