在Java项目上工作,我想知道线程是否已完成所需的计算。

首次尝试:Runnable中的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
第二次尝试:Runnable的调用者中的done
然后,我决定在KochManager中创建一个名为leftDone的变量,创建一个setter setLeftDone()并在EdgeGenerator中对其进行调用。这也总是重调为假。

经理:
公共(public)类KochManager {
私有(private)决赛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;
            ...
        }
    }
}

正如您可能已经猜想的那样,该方法也不起作用,因此,在进行了更多搜索之后,我决定使用另一个具有单个值的对象。

第三次尝试:创建将保存要设置的变量的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:
public class EdgeGenerator {
    ...
    @Override
    public synchronized void run() {
        ...
        switch (this.edgeLocation) {
            case LEFT:
                this.koch.generateLeftEdge();
                this.kochManager.setLeftDone(true);
                break;
            ...
        }
    }
}

一旦解决不了,我决定调用StackOverflow。
有人可以帮我吗?

最佳答案



您需要使用Option-1,但是将done变量标记为volatile,如下所示,,否则其他线程将不能保证看到done变量的更改。

private volatile boolean done;

以下是来自here的有关volatile的引用

10-05 21:19