コードは次のとおりです。基本的に、ReadCalculationクラスとCalculatorクラスをRunnableを実装する代わりにThreadを拡張するように変更した場合、これらのクラスをインスタンス化して新しいスレッドオブジェクトに渡すか、start()を呼び出す必要があります。拡張する代わりにRunnableを実装するときの動作が異なる
Calculator calc = new Calculator();
new ReadCalculation(calc).start();
new ReadCalculation(calc).start();
calc.start();
これまで何も特別..しかし、あなたは、この小さなプログラムを実行すると、あなたのスレッドは、「計算のために待っています...」ブロックされたままになることを我々は拡張の上にRunnableを実装上つもりなら、巨大なチャンスがありますThreadクラス
Runnableを実装する代わりにThreadクラスを拡張している場合、競合条件の兆候がなくても動作は正しいです。 この現象の原因となる可能性のあるアイデアはありますか?あなたがwait()
を実行すると
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'のソースコードは両方のスレッドで非常に多くのロックを必要とします。 class'と現在の 'Thread'インスタンスです。 'calc'の内側と外側の両方からCalculatorインスタンスをロックします。これらのロックは、専用のターゲットRunnableを使用するときに 'Thread'の内部でロックするのを妨げないかもしれません(Androidスレッド実装のコードは渡されたRunnableでロックされないようです)。 – user1643723