线程不可中断

thread is not interruptible

我正在努力研究著名的餐饮哲学家,它已经完成了,但是我很难尝试中断线程。

如您所知,在这个问题中我们有 5 个线程(哲学家),并且用户设置了实验结束的实验时间。

值得注意的是,我在 Whosebug 上查看了多个答案。

第一个来自@Konrad Reiche 如何在 Java 中终止线程? /计算器link

在那个特定的 post 中,人们已经声明使用 volatile 布尔值作为标志可能会成功,但我担心练习纸中说明我不能使用 volatile 布尔值来中断一个线程,但我可以将它用于其他目的。 (学习练习).

第二个是Thread interrupt() does not interrupt thread/Whosebug link

但没有任何帮助!

我会尽量提供必要的代码,希望有人能指出我的 mistake/s。 class 哲学家是 public 并扩展了线程!

1)第一次尝试:(如果他不希望我们使用 volatile boolean 作为标志,可能会被教授拒绝!)

像这样使用 volatile 布尔值时有效:

private volatile boolean isNotStopped=true;

@Override
public void stopPhilosopher() {
    System.out.printf("\n%s will stop.\n",selfPhilosopher.getName());
    selfPhilosopher.interrupt();
    isNotStopped=false;
}


@Override
public void run() {
    while (isNotStopped){//selfPhilosopher is a thread equals to this!.
        try {
                think();
                eat();
        } catch (InterruptedException e) {//somehow this was never triggered!.
            System.out.printf("%s was interrupted.\n",selfPhilosopher.getName());
        }finally {//in the finally block i always get RUNNER, FALSE
            System.out.printf("the %s is %s and is interrupted %b.\n", selfPhilosopher.getName(),selfPhilosopher.getState(), selfPhilosopher.isInterrupted());
        }
    }
}

第二次尝试[更新]:[工作中]

selfPhilosopher.isInterrupted() 替换为 Thread.currentThread().isInterrupted() 没有任何区别,因为 selfPhilosopher=this;

然而我从 stopPhilosopher() 方法得到 "will stop" 但线程似乎像僵尸一样不断复活:(

由于我非常相信 @Konrad Reiche from the first reference 提供的意见和@Nathan Hughes 的回答,我将坚持使用 java isInterrupted() 而不是使用易失性标志。

@Override
public void stopPhilosopher() {
    System.out.printf("\n%s will stop.\n",selfPhilosopher.getName());
    selfPhilosopher.interrupt();

}

@Override
public void run() {
    while (!selfPhilosopher.isInterrupted()){//selfPhilosopher is a thread equals to this!.
        try {
                think();
                eat();
        } catch (InterruptedException e) {//somehow this was never triggered!.Now it works.
            System.out.printf("%s was interrupted from catch clause!..\n",selfPhilosopher.getName());
            selfPhilosopher.interrupt();
        }
    }
}

输出:

 Philosopher2 in seat nr: 2 was interrupted from catch clause!..

当抛出 InterruptedException 时,中断标志被清除。这意味着您的循环进行的下一次检查将指示线程未被中断并且线程将继续 运行。当您的 finally 块为中断标志打印出 false 时,这就是您所看到的。

这在the API doc for the sleep method中有描述:

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

将此行添加到捕获 InterruptedException 的块中:

Thread.currentThread().interrupt();  // restores interrupt flag

首先:与 isInterrupted() 相比,我更喜欢 volatile 布尔标志 。它清晰、简洁且符合地道。 isInterrupted() 的必要结构更多地取决于细节(例如 try/catch 在你的情况下,因为似乎有一个 Thread.sleep (或类似的东西)声明 InterruptedException)。

由于您的示例中的 try/catch InterruptedException 在 while 循环中,中断被消耗并且需要重新发送到 selfPhilosopher (看起来有点可疑)。为避免这种情况,将 while 循环放入周围的 try-catch 中:

try {
    while (!selfPhilosopher.isInterrupted()) {
        think();
        eat();
    } 
} catch (InterruptedException e) {
    System.out.printf("%s was interrupted from catch clause!..\n",selfPhilosopher.getName());
    // not necessary anymore: selfPhilosopher.interrupt();
}

易失性布尔标志不需要重新发送,并且可以在两个星座中使用(在 try/catch 周围以及在 try 内)。

此外:假设您的 class 实现了 Runnable 并且没有扩展 Thread 那么您还需要注意在 [=20] 开头设置 selfPhilosopher =](没有其他地方)。