承上篇 103 — Multiple Threads
如果出現 Thread Interference 該怎麼解?
MultipleThreads.java
import thread.ThreadColor;public class MultipleThreads {
public static void main(String[] args) { Countdown countdown1 = new Countdown();
Countdown countdown2 = new Countdown(); CountdownThread t1 = new CountdownThread(countdown1);
t1.setName("Thread 1");
CountdownThread t2 = new CountdownThread(countdown2);
t2.setName("Thread 2"); t1.start();
t2.start(); }
}class Countdown {
private int i;
public void doCountdown() {
String color; switch (Thread.currentThread().getName()) {
case "Thread 1":
color = ThreadColor.ANSI_CYAN;
break;
case "Thread 2":
color = ThreadColor.ANSI_PURPLE;
break;
default:
color = ThreadColor.ANSI_GREEN;
}
for (i = 10; i > 0; i--) {
System.out.println(color + Thread.currentThread().getName() + ": i=" + i);
}
}
}class CountdownThread extends Thread {
private Countdown threadCountdown; public CountdownThread(Countdown countdown) {
this.threadCountdown = countdown;
} @Override
public void run() {
threadCountdown.doCountdown();
}
}
輸出結果:
Thread 2: i=10
Thread 2: i=9
Thread 2: i=8
Thread 2: i=7
Thread 2: i=6
Thread 2: i=5
Thread 2: i=4
Thread 2: i=3
Thread 2: i=2
Thread 1: i=10
Thread 1: i=9
Thread 1: i=8
Thread 1: i=7
Thread 1: i=6
Thread 1: i=5
Thread 1: i=4
Thread 1: i=3
Thread 1: i=2
Thread 1: i=1
Thread 2: i=1
簡單的解法就是,不要使用同一個 countdown
就好,現在拆成兩個,各自使用就不會有問題
但 Tim 也說了,現實中的應用是不太能使用這種解法
例如在銀行、員工系統。就不能有兩個同樣的 object
來做使用
像是銀行櫃台操作了客戶的帳戶,客戶也在網頁上操作帳戶,那兩個 object
的值不一樣時,最後要用哪一個?
會有不同 Thread
對帳戶進行操作,這種情況當然不能使用這種解法
修改 MultipleThreads.java
import thread.ThreadColor;public class MultipleThreads {
public static void main(String[] args) { Countdown countdown = new Countdown(); CountdownThread t1 = new CountdownThread(countdown);
t1.setName("Thread 1");
CountdownThread t2 = new CountdownThread(countdown);
t2.setName("Thread 2"); t1.start();
t2.start(); }
}class Countdown {
private int i;
public synchronized void doCountdown() {
String color; switch (Thread.currentThread().getName()) {
case "Thread 1":
color = ThreadColor.ANSI_CYAN;
break;
case "Thread 2":
color = ThreadColor.ANSI_PURPLE;
break;
default:
color = ThreadColor.ANSI_GREEN;
}
for (i = 10; i > 0; i--) {
System.out.println(color + Thread.currentThread().getName() + ": i=" + i);
}
}
}class CountdownThread extends Thread {
private Countdown threadCountdown; public CountdownThread(Countdown countdown) {
this.threadCountdown = countdown;
} @Override
public void run() {
threadCountdown.doCountdown();
}
}
輸出結果:
Thread 1: i=10
Thread 1: i=9
Thread 1: i=8
Thread 1: i=7
Thread 1: i=6
Thread 1: i=5
Thread 1: i=4
Thread 1: i=3
Thread 1: i=2
Thread 1: i=1
Thread 2: i=10
Thread 2: i=9
Thread 2: i=8
Thread 2: i=7
Thread 2: i=6
Thread 2: i=5
Thread 2: i=4
Thread 2: i=3
Thread 2: i=2
Thread 2: i=1
第二個解法則是使用 synchronized
先把 countdown
還原回去,變回原本的一個
然後在 doCountdown()
前面加上關鍵字 synchronized
這樣能確保只有一個 Thread
能使用該 Method
從輸出結果來看,可以看到一組用完才換下一組 Thread
這樣就不會出現 Thread Interference 的問題
修改 MultipleThreads.java
import thread.ThreadColor;public class MultipleThreads {
public static void main(String[] args) { Countdown countdown = new Countdown(); CountdownThread t1 = new CountdownThread(countdown);
t1.setName("Thread 1");
CountdownThread t2 = new CountdownThread(countdown);
t2.setName("Thread 2"); t1.start();
t2.start(); }
}class Countdown {
private int i; public void doCountdown() {
String color; switch (Thread.currentThread().getName()) {
case "Thread 1":
color = ThreadColor.ANSI_CYAN;
break;
case "Thread 2":
color = ThreadColor.ANSI_PURPLE;
break;
default:
color = ThreadColor.ANSI_GREEN;
}
synchronized (this) {
for (i = 10; i > 0; i--) {
System.out.println(color + Thread.currentThread().getName() + ": i=" + i);
}
}
}
}class CountdownThread extends Thread {
private Countdown threadCountdown; public CountdownThread(Countdown countdown) {
this.threadCountdown = countdown;
} @Override
public void run() {
threadCountdown.doCountdown();
}
}
輸出結果:
Thread 1: i=10
Thread 1: i=9
Thread 1: i=8
Thread 1: i=7
Thread 1: i=6
Thread 1: i=5
Thread 1: i=4
Thread 1: i=3
Thread 1: i=2
Thread 1: i=1
Thread 2: i=10
Thread 2: i=9
Thread 2: i=8
Thread 2: i=7
Thread 2: i=6
Thread 2: i=5
Thread 2: i=4
Thread 2: i=3
Thread 2: i=2
Thread 2: i=1
這是第二種 Synchronisation 的用法
對 statement 做 synchronisation
但要特別注意使用的變量
這裡就滿困難的
看了討論區很多的 QA ,我還是霧沙沙
關鍵全部的 Thread
都要能訪問到同一個變量
變量的篩選要特別注意
補充資料:Synchronized Methods