Java线程不会被中断

标签 java multithreading

我正在使用线程开发一个 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/

相关文章:

C#线程间通信

java - 为什么按钮不反射(reflect) Action 的 NAME 属性?

java - 我可以从 Java 应用程序填写 PDF 模板吗?如何?

Python:将参数传递给 threading.Thread 实例的正确方法是什么

multithreading - Cocoa线程无法访问Cocoa API

c++ - 在线程之间发送窗口消息时出现 ESP 错误

java - 将网格集成到页面对象模型中

java - 使用java实现定时器任务

java - 为什么 EditText 没有通过 setFillAfter(true) 获得焦点?

python - 如何在发生错误时重新执行 ThreadPoolExecutor 中的函数?