在代码的任何位置使用 GUI 按钮中断线程

问题描述 投票:0回答:1

最近我正在编写代码,该代码可以自动执行许多任务,例如查找到特定目标的路径(通过 A* 算法)并相应地移动 2D 地图中所有找到的节点。我试图在 Swing 中实现 GUI,以便我可以控制代码的行为。我创建了简单的片段:

@Component
public class BotGUI {


    private boolean isRunning = true;

    @Autowired
    private BotInit botInit;

    private Thread botThread;

    public void stopBot() {
        if (this.botThread != null) {
            botThread.interrupt();
        }
    }

    public boolean isRunning() {
        return this.isRunning;
    }

    public BotGUI() {

    }

    public void startGUI() {

        this.botThread = new Thread(botInit);
        botThread.start();

        JFrame jFrame = new JFrame("MagBot Control Panel");
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setSize(300, 100);

        JButton toggleButton = new JButton("Stop Bot");
        toggleButton.setBackground(Color.lightGray);
        toggleButton.setForeground(Color.blue);
        toggleButton.setFont(new Font("Arial", Font.BOLD, 16));
        Border lineBorder = BorderFactory.createLineBorder(Color.darkGray);
        toggleButton.setBorder(lineBorder);
        toggleButton.setMargin(new Insets(5, 15, 5, 15));
        toggleButton.setOpaque(true);
        toggleButton.setContentAreaFilled(false);
        toggleButton.addActionListener(e -> {
            if (this.isRunning()) {
                this.stopBot();
                toggleButton.setText("Start Bot");
            } else {
                this.botThread = new Thread(botInit);
                botThread.start();
                toggleButton.setText("Stop Bot");
            }

            this.isRunning = !isRunning;
        });

        jFrame.getContentPane().add(toggleButton, BorderLayout.CENTER);
        jFrame.setVisible(true);
    }
}

这段代码尝试中断正在运行某些任务的线程。但随后出现了一个问题 - 为了正确处理中断,我必须实施持续的

isInterrupted()
检查或依靠捕获
InterruptedException
并将其传播得越来越高。我的代码中有很多抽象级别,并且在处理此类任务时遇到问题 - 我尝试过发送垃圾邮件按钮来停止/启动我的程序,尽管在代码中的关键位置进行了中断检查,但它没有帮助。我可能会在某个不知道线程中断的
for
循环中中断线程。遇到这样的问题怎么处理?

如何中断线程而不在代码中到处放置

try
catch
块?它看起来不干净,我怀疑这是一个好的做法。

我的代码示例:

            while (!Thread.currentThread().isInterrupted()) {
                bot.processWalkAndAttack();
                TimeUnit.MILLISECONDS.sleep(2000);
            }

        } catch (InterruptedException var3) {

            log.error("Bot stopped.");
        }
    public void processWalkAndAttack() {

        try {
            List<Monster> monsters = utilityFunction.convertToMonsters();
            Monster closestMonster = utilityFunction.findClosestMonster(monsters);
            moveModule.moveToTarget(closestMonster.getPosition());
            utilityFunction.attackMob();
        } catch (InterruptedException e) {
            log.error("Interrupted!");
            Thread.currentThread().interrupt();
        }

    }

我没有在每个函数调用中进行中断检查,因为我的代码很大,而且这样的检查似乎效率不高。因此,某些线程有可能不会被停止,并且尽管被中断,代码仍会运行,因为在某些

for
循环或某些实用方法中,我们没有声明线程被中断时的场景。

java multithreading exception interrupted-exception
1个回答
0
投票

你是对的..如果在线程中运行的一段代码可以是“常规”Java 代码,它不是线程感知的,并且该代码可以在需要时从外部中断,那就太好了。但是,似乎没有一个好的方法可以做到这一点。

一些建议:

  1. 我相信你不需要 try/catch 除非你要“睡觉”或“等待”。如果可能的话,您只需要更频繁地检查 isInterrupted() 即可。
  2. 您可以拥有另一个线程和一个进度条,供用户等待直到线程停止 - 显示一个旋转器直到线程响应,从而为用户提供更好的体验。
  3. Java 中的真实线程确实会因 I/O 而被阻塞。因此,只有在 I/O 块打开后,JVM 才能中断线程。这可能在虚拟线程中可以更好地处理。由于虚拟线程被停顿,即使在 I/O 上被认为“阻塞”时,它也可能能够响应中断。因此,在 Java 21 上运行程序并使用新的 VirtualThread 可能会使您的程序响应更快。
© www.soinside.com 2019 - 2024. All rights reserved.