【问题标题】:Java thread not stopping even after calling interruptJava线程即使在调用中断后也不会停止
【发布时间】:2015-11-28 08:46:20
【问题描述】:

我在第 370 天调用中断,然后在其他类的 run 方法期间的 catch 块期间再次调用它。我也有一个 while 条件循环,而线程没有被中断,但由于某种原因,它不起作用,我不知道为什么。我知道我可以改用变量标志,但我想尝试让 interrupt() 工作。我已经查看了多个站点,但似乎没有一个对我有用。请帮忙。

public class Elf implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            // wait a day
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

public class Main {
    public static void main(String args[]) {
        Scenario scenario = new Scenario();
        // create the participants
        // Santa
        scenario.setSanta( new Santa(scenario) );
        Thread th = new Thread(scenario.getSanta());
        th.start();
        // The elves: in this case: 10
        for (int i = 0; i != 10; i++) {
            Elf elf = new Elf(i + 1, scenario);
            scenario.getElves().add(elf);
            th = new Thread(elf);
            th.start();
        }
        // The reindeer: in this case: 9
        for (int i = 0; i != 9; i++) {
            Reindeer reindeer = new Reindeer(i + 1, scenario);
            scenario.getReindeers().add(reindeer);
            th = new Thread(reindeer);
            th.start();
        }
        // now, start the passing of time
        for (int day = 1; day < 500; day++) {
            // wait a day
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            // turn on December
            if (day > (365 - 31)) {
                scenario.setDecember(true);
            }
            // interrupt flag is set here
            if (day == 370) {
                th.interrupt();
            }
            // print out the state:
            System.out.println("***********  Day " + day
                    + " *************************");
            scenario.getSanta().report();
            for (Elf elf : scenario.getElves()) {
                elf.report();
            }
            for (Reindeer reindeer : scenario.getReindeers()) {
                reindeer.report();
            }
        }
    }
}

我在这里只包含了 Elf 类,但其他类的结构相同,其中的代码几乎相同。现在程序结束,红色方块(终止按钮)仍然亮着,我读到这表明仍有线程在运行。我不知道为什么它没有停止。

【问题讨论】:

  • 您的th 只是指向最后一只驯鹿。所以th.interrupt() 只是打断那只驯鹿,没有其他线程。
  • 您将需要存储对您稍后想要中断的所有线程的引用。
  • 哦,我不知道。我认为th 指向所有线程,而不仅仅是前一个。谢谢!
  • 只为第一个圣诞节 var 名称投票。

标签: java multithreading interrupt


【解决方案1】:

声明为Thread th 的变量是对Thread 类型对象的引用。它只是对一个对象的引用。顺便说一句,这对所有类型都是正确的,而不仅仅是线程。

每当您将新值放入变量时,它不再引用旧值[1]

因此,您的代码中的th.interrupt() 只会中断您分配给它的最后一个线程——最近的驯鹿线程。

如果要中断所有线程,则需要保留对所有线程的引用。

基本解决方案

一个简单的方法是使用Thread的列表:

List<Thread> allThreadsToInterrupt = new ArrayList<>();

当你创建一个线程时,你会这样做

th = new Thread(...);
allThreadsToInterrupt.add(th);

最后你可以这样做:

for ( Thread th: allThreadsToInterrupt ) {
    th.interrupt();
}

使用ThreadGroup

但事实上,Java 有一个现有的类可以帮助您解决这个问题 - ThreadGroup 类。您可以执行以下操作:

ThreadGroup elfThreads = new ThreadGroup("Elf Threads");
ThreadGroup reindeerThreads = new ThreadGroup( "Reindeer Threads" );

现在,无论何时创建线程,都应该使用线程组来创建它:

代替:

th = new Thread(elf);

用途:

th = new Thread(elfThreads,elf);

那么最后,要打断所有精灵,你可以跑:

elfThreads.interrupt();

这将在属于该组的所有线程上自动调用interrupt()

当然,你可以只创建一个大组,但我演示了将精灵和驯鹿分开,以防你需要将它们分开打断。


[1] 在大多数情况下,用新引用替换旧引用(它是对对象的唯一引用)会导致旧对象符合垃圾回收条件,但线程有点不同,因为如果它们有已启动,从当前线程组有第二次引用它们(因为这是默认的,当您创建线程时不提供线程组时),这意味着它们不会被垃圾收集并且它们将运行直到他们完成为止。

【讨论】:

  • 谢谢,您的回答对我理解多线程的工作原理有很大帮助。
猜你喜欢
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
  • 2018-06-17
  • 2023-04-08
相关资源
最近更新 更多