多執行緒案例 Java
1、購票(不安全策略)
程式碼片段:
public class Main { private static int ticket = 10; public static void main(String[] args) { Runnable r = new Runnable() { public void run() { while(ticket > 0) { try { ticket--; Thread.sleep(1000); System.out.println("賣出了一張票,還剩下"+ticket+"張票"); }catch (Exception e) { e.printStackTrace(); } } } }; new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); } }
顯示結果:
賣出了一張票,還剩下6張票
賣出了一張票,還剩下5張票
賣出了一張票,還剩下5張票
賣出了一張票,還剩下5張票
賣出了一張票,還剩下2張票
賣出了一張票,還剩下2張票
賣出了一張票,還剩下2張票
賣出了一張票,還剩下2張票
賣出了一張票,還剩下0張票
賣出了一張票,還剩下0張票
2、購票(安全策略)
- 給方法加入synchronized解決執行緒不安全問題
程式碼片段:
public class Main { private static int ticket = 10; public static void main(String[] args) { Runnable r = new Runnable() { public synchronized void run() { while(ticket > 0) { try { ticket--; Thread.sleep(1000); System.out.println("賣出了一張票,還剩下"+ticket+"張票"); }catch (Exception e) { e.printStackTrace(); } } } }; new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); } }
顯示結果:
賣出了一張票,還剩下9張票
賣出了一張票,還剩下8張票
賣出了一張票,還剩下7張票
賣出了一張票,還剩下6張票
賣出了一張票,還剩下5張票
賣出了一張票,還剩下4張票
賣出了一張票,還剩下3張票
賣出了一張票,還剩下2張票
賣出了一張票,還剩下1張票
賣出了一張票,還剩下0張票
注:第一個執行緒進入run()後,其他程序無法進入,直到第一個執行緒執行完畢才允許其他程序進入,而此時ticket已經為0,其他程序不能進入迴圈體,因此,退出。
其中,形如synchronized (Main.class) {}包含程式碼塊的結構也能達到同樣的效果。
3、wait()和notify()
程式碼片段:
public class Main {
public static void main(String[] args) {
new Thread() {
public void run() {
synchronized (Main.class) {
System.out.println("T1 start!");
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 end!");
}
}
}.start();
new Thread() {
public void run() {
synchronized (Main.class) {
System.out.println("T2 start!");
Main.class.notify(); //喚醒
System.out.println("T2 end!");
}
}
}.start();
}
}
結果顯示:
T1 start!
T2 start!
T2 end!
T1 end!
解析:wait()和notify()一系列的方法,是屬於物件的,不是屬於執行緒的。它們用線上程同步時,synchronized語句塊中。
wait()方法可以使執行緒進入等待狀態,而notify()可以使等待的狀態喚醒。這樣的同步機制十分適合生產者、消費者模式:消費者消費某個資源,而生產者生產該資源。當該資源缺失時,消費者呼叫wait()方法進行自我阻塞,等待生產者的生產;生產者生產完畢後呼叫notify/notifyAll()喚醒消費者進行消費。
4、wait()
和notify()
精細控制
程式碼片段:
public class Main {
public static void main(String[] args) {
final Object object = new Object();
new Thread() {
public void run() {
synchronized (object) {
System.out.println("T1 start!");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 end!");
}
}
}.start();
new Thread() {
public void run() {
synchronized (object) {
System.out.println("T2 start!");
object.notify();
System.out.println("T2 end!");
}
}
}.start();;
new Thread() {
public void run() {
synchronized (object) {
System.out.println("T3 start!");
object.notify();
System.out.println("T3 end!");
}
}
}.start();;
new Thread() {
public void run() {
synchronized (object) {
System.out.println("T4 start!");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T4 end!");
}
}
}.start();
}
}
結果顯示:
T1 start!
T2 start!
T2 end!
T1 end!
T3 start!
T3 end!
T4 start!
很容易看出來,T4,它啟動了,但是wait了,後面已經沒有執行緒了,它的wait永遠不會有執行緒幫它notify了!於是,T4 (T4 end!沒法執行到)它就這麼等著!