所以這裏是代碼。 基本上,如果我們改變ReadCalculation和Calculator類來擴展Thread而不是實現Runnable,我們需要實例化這些類並將它們傳遞給一個新的線程對象,或者只需在它們上調用start()。實現Runnable時不同的行爲,而不是延長線程
Calculator calc = new Calculator();
new ReadCalculation(calc).start();
new ReadCalculation(calc).start();
calc.start();
沒什麼特別的,到目前爲止..但是,當你執行這個小程序,有一個巨大的機會,你的線程將保持阻塞「等待計算......」如果我們上延伸渡過了Runnable接口的實現Thread類。
如果我們擴展Thread類而不是實現Runnable,那麼行爲是正確的,沒有任何競爭條件。 任何想法都可能是此行爲的來源?
public class NotifyAllAndWait {
public static void main(String[] args) {
Calculator calc = new Calculator();
Thread th01 = new Thread(new ReadCalculation(calc));
th01.start();
Thread th02 = new Thread(new ReadCalculation(calc));
th02.start();
Thread calcThread = new Thread(calc);
calcThread.start();
}
}
class ReadCalculation implements Runnable {
private Calculator calc = null;
ReadCalculation(Calculator calc) {
this.calc = calc;
}
@Override
public void run() {
synchronized (calc) {
try {
System.out.println(Thread.currentThread().getName() + " Waiting for calculation...");
calc.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " Total: " + calc.getTotal());
}
}
}
class Calculator implements Runnable {
private int total = 0;
@Override
public void run() {
synchronized(this) {
System.out.println(Thread.currentThread().getName() + " RUNNING CALCULATION!");
for(int i = 0; i < 100; i = i + 2){
total = total + i;
}
notifyAll();
}
}
public int getTotal() {
return total;
}
}
我不能引用語言或JVM規範的任何部分,這可能在這裏,但最可能的實際原因是'Thread'源代碼在'Thread'上佔用了很多鎖。類'和當前'線程'實例。 'calc'的內部和外部都可以鎖定Calculator實例。當你使用專用目標Runnable時,這些鎖可能不會干擾'Thread'內部的鎖定(只是選中:Android Thread實現中沒有任何代碼會鎖定傳遞的Runnable),但當擴展Thread時肯定會影響執行順序。 – user1643723