如何完全停止执行线程

时间:2018-12-06 11:11:03

标签: java multithreading intellij-idea

我搜索了StackOverflow,但是找不到我的问题的答案。

我有一个主班:-

public class Main {
    public static Thread game = new Thread(new Start());
    public static void main(String[] args) {
        game.start();
        try {
            game.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

我有游戏Thread(start class):-

public class Start implements Runnable {
    private Timer timer = new Timer();
    private Thread timerThread = new Thread(timer, "timer");
    @Override
    public void run() {
        ...
        try {
            play();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
    public void play() throws IOException {
        ...
        timerThread.run();
        System.out.print("Enter a letter: ");
        char input = sc.next().toUpperCase().charAt(0);
        ...
        if(isPlaying) play();
    }
}

我有Timer类:-

public class Timer implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 15; i++) {
            try {
                System.out.println(i);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Main.game.interrupt();
    }
}

现在问题来了,当我开始游戏时,计时器也会启动。但是在15秒结束时,计时器线程停止。但是程序没有停止执行。

15秒后,编译器仍然愿意接受输入。输入后,程序停止。

我想立即强制停止线程。 15秒后不久,我想在那一刻停止执行游戏线程。

我查看了Youtube上的一些多线程教程以及StackOverflow上的一些以前的问题,但是我找不到解决方案。

2 个答案:

答案 0 :(得分:2)

您收到NullPointerException吗?

我测试了您的解决方案,这就是我得到的。 如果是这种情况,那么您的问题是,在初始化game类中的静态属性之前,您正在尝试初始化Timer中的Main字段。

为了您的理解,让我改写一下: 代码运行时

private Thread game = Main.game;

Main.game中没有任何内容,这是因为Main.game将在StartTimer实例初始化之后初始化。

解决该问题的最简单方法是删除计时器的private Thread game属性,然后调用Main.game.interrupt();

编辑01: 解决第一件事后,您需要了解线程中断的工作方式。 调用Main.game.interrupt();时,只有在线程处于休眠状态时,才立即将其停止。如果是这种情况,线程将抛出InterruptedException,但这不是我们想要的,因此我不建议这样做。在正常流程中,执行.interrupt()方法会将目标线程的状态设置为“中断”,但这只是一个boolean标志,不会改变任何东西(尚未)。您需要做的是检查递归方法中该标志的状态,以便在“ interruption”标志的值等于true时,将isPlaying的值更改为false。这就是您的线程停止的方式。

在代码中将是这样的:

public void play() throws IOException {
        ...
        timerThread.run();
        System.out.print("Enter a letter: ");
        char input = sc.next().toUpperCase().charAt(0);
        if (Thread.interrupted()) {
            System.out.println("I should interrupt myself! ;)");
            isPlaying = false;
        }
        ...
        if(isPlaying) play();
}

希望这会有所帮助:)

答案 1 :(得分:1)

我认为使用Thread.interrupt()是一种完全可以接受的方法。