我正在使用线程开发一个 Java 程序,并且不断遇到一些问题,我希望有人可以帮助我解决这个问题。
这是一个学校项目,我们必须制作一些科赫分形。
第一类是经理。 这是创建线程以使用 EdgeGenerator 生成科赫分形边缘的位置。
import java.util.logging.Level;
import java.util.logging.Logger;
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();
try {
tLeft.join(500);
tRight.join(500);
tBottom.join(500);
} catch (InterruptedException ex) {
Logger.getLogger(KochManager.class.getName()).log(Level.SEVERE, null, ex);
}
application.requestDrawEdges();
}
public void addEdge(Edge edge){
this.edges.add(edge);
}
public synchronized void increaseCount(){
count ++;
}
public int getLevel() {
return level;
}
}
第二个类是 EdgeGenerator,它实现了 Runnable 和 Observer。
可观察的是 KochFractal 类(此处不包括)。 update 方法在 KochFractal 的generate__Edge() 方法上调用。 这一切都工作得很好,并且在不使用线程和使用线程的情况下进行了测试。
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;
public EdgeGenerator(KochManager kochManager, EdgeLocation edgeLocation) {
this.kochManager = kochManager;
this.edgeLocation = edgeLocation;
this.koch = new KochFractal();
this.koch.addObserver(this);
}
@Override
public void run() {
koch.setLevel(kochManager.getLevel());
switch (this.edgeLocation) {
case LEFT:
this.koch.generateLeftEdge();
break;
case RIGHT:
this.koch.generateRightEdge();
break;
case BOTTOM:
this.koch.generateBottomEdge();
break;
}
Thread.currentThread().interrupt();
}
@Override
public void update(Observable o, Object o1) {
this.kochManager.addEdge((Edge)o1);
this.kochManager.increaseCount();
}
}
这里的最后一个类是使用 ArrayList 的集合类。 在添加和删除时我使用了同步关键字。据我了解,这使得实例方法一次只能由一个线程访问,并使其他线程处于搁置状态。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class EdgeArrayList implements IEdgeCollection{
private final List<Edge> edges;
public EdgeArrayList() {
this.edges = new ArrayList<>();
}
@Override
public synchronized void add(Edge e) {
edges.add(e);
}
@Override
public synchronized void remove(Edge e) {
edges.remove(e);
}
@Override
public void clear() {
edges.clear();
}
@Override
public List<Edge> getAll() {
return Collections.unmodifiableList(edges);
}
}
那么这是怎么回事呢?
- 当我运行这里实现的程序时,GUI 中只显示了所有分形元素中的一小部分。
然而,一旦需要计算大量边,GUI 中显示的边就会越来越少。
使用调试器,我可以看到所有边缘都已计算完毕,但在计算所有边缘之前调用了
application.requestDrawEdges();
。 - 当我在
join()
方法中没有延迟地运行程序时,它只是继续运行而不显示 gui。
据我所知Thread.currentThread().interrupt();
应该停止当前线程并调用join()
方法,但这并没有发生。
我希望有人能给我指明正确的方向。
最佳答案
你对join的理解是错误的。
您的主线程将简单地等待 500 毫秒让每个地下元素加入...但如果没有发生,代码执行将继续。换句话说:大约 1.5 秒后绘图将开始。
您可以让每个子线程主动宣布“我完成了”,而不是使用低级原始连接。而你的主线程只是等待所有子线程执行此操作。
除此之外:线程对象非常“昂贵”。你真的不应该在每次迭代后扔掉它们。相反:考虑使用 ExecutorService 来代替。您最初创建一项服务,然后将新任务推送到该服务中。与 Futures 一起应该可以提供更优雅的解决方案。正如 Hovercraft 建议的那样,您还可以允许更频繁地更新用户界面。
关于Java线程不会被中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42879379/