Javaプロジェクトで作業しており、スレッドが必要な計算を完了したかどうかを知りたいと思います。スレッドがJavaで終了したかどうかを知る方法?
は最初の試み:実行可能
でdone
変数は、最初のクラスは、マネージャ
import uckochfractalfx.UCKochFractalFX;
public class KochManager {
private final UCKochFractalFX application;
private final IEdgeCollection edges;
private int level;
private int count;
public KochManager(UCKochFractalFX application) {
this.application = application;
this.edges = new EdgeArrayList();
}
public synchronized void changeLevel(int nxt) {
this.level = nxt;
this.count = 0;
this.edges.clear();
EdgeGenerator left, right, bottom;
left = new EdgeGenerator(this, EdgeLocation.LEFT);
right = new EdgeGenerator(this, EdgeLocation.RIGHT);
bottom = new EdgeGenerator(this, EdgeLocation.BOTTOM);
Thread tLeft, tRight, tBottom;
tLeft = new Thread(left);
tRight = new Thread(right);
tBottom = new Thread(bottom);
tLeft.start();
tRight.start();
tBottom.start();
while (!(left.isDone() && right.isDone() && bottom.isDone()) {
wait();
}
this.application.setTextCalc(String.valueOf(this.totalTimeExecution));
this.application.setTextNrEdges(String.valueOf(this.count));
application.requestDrawEdges();
}
public synchronized void addEdge(Edge edge) {
this.edges.add(edge);
}
public synchronized void increaseCount() {
count++;
}
public int getLevel() {
return level;
}
public void drawEdges() {
this.application.clearKochPanel();
this.edges.getAll().forEach((Edge e) -> this.application.drawEdge(e));
this.application.setTextDraw(String.valueOf(this.totalTimeExecution));
}
}
であり、これは
import java.util.Observable;
import java.util.Observer;
public class EdgeGenerator implements Runnable, Observer {
private final KochManager kochManager;
private final EdgeLocation edgeLocation;
private final KochFractal koch;
private boolean done;
public EdgeGenerator(KochManager kochManager, EdgeLocation edgeLocation) {
this.kochManager = kochManager;
this.edgeLocation = edgeLocation;
this.koch = new KochFractal();
this.koch.addObserver(this);
}
@Override
public synchronized void run() {
koch.setLevel(kochManager.getLevel());
this.done = false;
switch (this.edgeLocation) {
case LEFT:
this.koch.generateLeftEdge();
break;
case RIGHT:
this.koch.generateRightEdge();
break;
case BOTTOM:
this.koch.generateBottomEdge();
break;
}
this.done = true;
}
public boolean isDone() {
return done;
}
@Override
public void update(Observable o, Object o1) {
this.kochManager.addEdge((Edge) o1);
this.kochManager.increaseCount();
}
}
すべてはなく、一つのことを作品EdgeGeneratorクラスであり、それは、スレッド内のオブジェクトの値をメインスレッドに戻します。
ここでは、EdgeGenerator
クラスのdone
に焦点を当てたい変数を使用します。
私はここでいくつかの方法を試しました。
最初のコードは上記のコードで確認できます。isDone()
を呼び出して返す必要があるすべての計算後にthis.done
を設定します。 isDone()
を呼び出すとき
しかし、それは常にfalse
第二の試みを返します。
実行可能
の呼び出し元でdone
それから私は、
leftDone
と呼ばれる
KochManager
で変数を作成セッター
setLeftDone()
を作成し、
EdgeGenerator
でそれを呼び出すことにしました。これはまた常に偽を返します。
マネージャ: public class KochManager { private final leftDone; ...
public void setLeftDone(boolean done) {
this.leftDone = done;
}
...
public synchronized void changeLevel(int nxt) {
...
while (!(this.leftDone && this.rightDone && this.BottomDone)){
wait();
}
...
}
}
EdgeGenerator:
public class EdgeGenerator {
...
@Override
public synchronized void run() {
...
switch (this.edgeLocation) {
case LEFT:
this.koch.generateLeftEdge();
this.kochManager.setLeftDone(true);
break;
...
}
}
}
ご想像のとおり、いくつかのより多く検索した後、私は単一の値を持つことになり、別のオブジェクトを使用することにしましたので、どちらか動作しませんでした。
第3の試み:設定する変数を保持するクラスDone
を作成します。
マネージャー:
public class KochManager {
private class Done {
public boolean done;
}
...
private Done leftDone;
public KochManager(UCKochFractalFX application) {
this.application = application;
this.edges = new EdgeArrayList();
this.leftDone = new Done();
}
public void setLeftDone(boolean done) {
this.leftDone.done = done;
}
...
public synchronized void changeLevel(int nxt) {
...
while (!(this.leftDone.done && this.rightDone.done && this.BottomDone.done)){
wait();
}
...
}
}
EdgeGenerator:これがうまくいかなかった後はどちらか、私はStackOverflowのの助けを呼ぶことにしました
public class EdgeGenerator {
...
@Override
public synchronized void run() {
...
switch (this.edgeLocation) {
case LEFT:
this.koch.generateLeftEdge();
this.kochManager.setLeftDone(true);
break;
...
}
}
}
。 誰かが私を助けてくれますか?
あなたの最初のアプローチの問題は、 'done'は、揮発性(と' isDone(ではないということです) 'ではありません同期されているため)、コードはスレッドセーフではなく、古い 'false'値を取得している可能性があります。 – Kayaman
これを処理するために 'Executor'を使って' Future'のようなものを使うことをお勧めします。 – Kayaman
'wait()'の呼び出しが何を理解していますか?実際に 'notify()'を呼びますか? –