处理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));
}
}
这是EdgeGenerator类
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();
}
}
一切都可以,但有一点,那就是将线程中对象的值返回给主线程。
我想关注的变量是done
类中的EdgeGenerator
。
我在这里试过几种方法。
首先是您可以在上面的代码中看到的实现:在所有计算之后设置this.done
,然后通过调用isDone()
返回。{
但是,在致电isDone()
时,它始终会返回false
done
在runnable 然后我决定在名为KochManager
的{{1}}中创建一个变量,创建一个setter leftDone
并在setLeftDone()
中调用它。这也总是重新虚假。
管理器: 公共类KochManager { 私人决赛leftDone; ...
EdgeGenerator
EdgeGenerator:
public void setLeftDone(boolean done) {
this.leftDone = done;
}
...
public synchronized void changeLevel(int nxt) {
...
while (!(this.leftDone && this.rightDone && this.BottomDone)){
wait();
}
...
}
}
正如您可能已经猜到的那样也不起作用,所以经过一些搜索之后,我决定使用另一个具有单个值的对象。
public class EdgeGenerator {
...
@Override
public synchronized void run() {
...
switch (this.edgeLocation) {
case LEFT:
this.koch.generateLeftEdge();
this.kochManager.setLeftDone(true);
break;
...
}
}
}
。管理器:
Done
EdgeGenerator:
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();
}
...
}
}
一旦这没有成功,我决定拨打StackOverflow的帮助。 有人可以帮助我吗?
答案 0 :(得分:5)
然而,当调用isDone()时,它总是返回false
您需要使用选项-1,但将done
变量标记为volatile
,如下所示,否则其他线程将无法保证看到done
的更改1}}变量。
private volatile boolean done;
以下是here关于volatile
对volatile变量的更改始终对其他线程可见。 更重要的是,它还意味着当线程读取volatile时 变量,它不仅看到了对volatile的最新变化,而且还看到了变量 导致变化的代码的副作用。
答案 1 :(得分:1)
你的代码的问题在于你有一个常见的并发问题:内存可见性。当一个线程更新完成时,其他人不会看到它已更新。您必须将 done 变量声明为volatile,以防止此问题发生:
volatile boolean done;
答案 2 :(得分:0)
问题是缓存了done
的值。您需要将其标记为volatile
,以便从各个线程调用它始终获得最新值。