gpt4 book ai didi

即使调用中断后,Java 线程也不会停止

转载 作者:行者123 更新时间:2023-11-30 03:09:18 26 4
gpt4 key购买 nike

我在第 370 天调用中断,然后在其他类的 run 方法期间的 catch block 期间再次调用它。我还有一个 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 类,但其他类具有相同的结构,其中的代码几乎相同。现在,程序结束时红色方 block (终止按钮)仍然亮起,我读到这表明仍有线程在运行。我不知道为什么它不停止。

最佳答案

声明为 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类(class)。您可以执行以下操作:

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

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

而不是:

th = new Thread(elf);

用途:

th = new Thread(elfThreads,elf);

最后,要打断所有 Sprite ,你可以运行:

elfThreads.interrupt();

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

当然,您可以只创建一大组,但我演示了将 Sprite 和驯鹿分开,以防您需要单独打断它们。

<小时/>

[1] 在大多数情况下,用新引用替换旧引用(这是对对象的唯一引用)将导致旧对象有资格进行垃圾回收,但线程略有不同,因为如果它们有启动后,当前线程组中有对它们的第二个引用(因为这是默认情况,当您创建线程时没有给出线程组时),这意味着它们不会被垃圾收集并且它们将运行正确地直到完成。

关于即使调用中断后,Java 线程也不会停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33969404/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com