How do I know if a thread has completed in Java?

Work on a Java project, and I would like to know if the thread has completed the necessary calculations.

First try: variable donein runnable

First class is a manager

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));
    }
}

And this is the EdgeGenerator class

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();
    }
}

Everything works only one, and this returns the values ​​from the objects in the stream back to the main stream.

The variable that I would like to focus on is donein the classroom EdgeGenerator.

I tried several ways here.

First, this is an implementation, as you can see in the above code: Set this.doneafter all the calculations that should then be returned by the call isDone().
However, when called, isDone()it always returnsfalse

Second attempt: donein the runnable calling file

KochManager, leftDone, setter setLeftDone() EdgeGenerator. .

:    KochManager {        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;
            ...
        }
    }
}

, , , , , .

: 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. - ?

+4
3

isDone() false

Option-1, done volatile, , , done.

private volatile boolean done;

volatile

volatile . , , , , , .

+5

, concurrency: . , , . , , :

volatile boolean done;
+1

The problem is caching the value done. You must mark it as volatileso that calls to it from different streams always receive the most modern value.

0
source

Source: https://habr.com/ru/post/1672668/


All Articles