нить не прерывается

Я пытаюсь работать над знаменитыми обеденными философами, и это почти закончено, но мне довольно трудно прерывать темы.

итак, как вы знаете, в этой задаче у нас есть 5 потоков (философов), и пользователь устанавливает время эксперимента, по истечении которого эксперимент закончится.

стоит отметить, что я просмотрел несколько ответов на StackOverflow.

Первый от @Konrad Reiche Как убить поток в Java? /Ссылка на StackOverflow

В этом конкретном посте люди заявили, что использование volatile boolean в качестве флага может сработать, но я боюсь, что в упражнении указано, что я не могу использовать volatile boolean для прерывания потока, но я могу использовать его для других целей. . (учебное упражнение).

Второй - Thread interrupt() не прерывает поток/ссылку Stackoverflow

пока ничего толком не помогло!.

Я постараюсь предоставить необходимый код и надеюсь, что кто-то просто укажет на мою ошибку/ошибки. класс Philosopher является общедоступным и расширяет Thread!.

1) Первая попытка: (может быть отклонена профессором, если он не хочет, чтобы мы использовали volatile boolean в качестве флага!)

при использовании volatile boolean, как это работает:

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(), но потоки, похоже, продолжают возвращаться к жизни зомби :(

из-за того, что я вполне убежден мнением @Konrad Reiche из первой предоставленной ссылки и ответом @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!..

person StudentAccount4    schedule 02.04.2020    source источник
comment
поток не будет прекращен или прерван. Вы говорите, что никогда не видели сообщение {name} было прервано с первой попытки?   -  person Joni    schedule 03.04.2020
comment
нет, предложение catch вообще не сработает. все, что я вижу, это блок finally, который напечатает имя и состояние RUNNER с FALSE.   -  person StudentAccount4    schedule 03.04.2020


Ответы (2)


Когда генерируется InterruptedException, флаг прерывания сбрасывается. Это означает, что следующая проверка вашего цикла покажет, что поток не прерван и продолжит работу. Это то, что вы видите, когда ваш блок finally выводит false для флага прерывания.

Это описано в документ API для метода сна:

InterruptedException - если какой-либо поток прервал текущий поток. Прерванное состояние текущего потока сбрасывается, когда выдается это исключение.

Добавьте эту строку в блок, где вы перехватываете InterruptedException:

Thread.currentThread().interrupt();  // restores interrupt flag
person Nathan Hughes    schedule 02.04.2020
comment
в первую очередь спасибо за помощь. Сэр, как написано в коде, блок catch в предложении catch метода run почему-то никогда не срабатывает. Так не могли бы вы сказать мне, какая польза от этого?! - person StudentAccount4; 03.04.2020
comment
@studentaccount4: если вы не вызовете сон, InterruptedException не будет создано. о, у тебя другая ошибка. - person Nathan Hughes; 03.04.2020
comment
@studentaccount4: попробуйте изменить тест !selfPhilosopher.isInterrupted() на !Thread.currentThread().isInterrupted(), вы уверены, что опубликованный код воспроизводит проблему? - person Nathan Hughes; 03.04.2020
comment
оказалось, что какая-то другая ошибка вызывала сцепление. но не могли бы вы дать мне несколько небольших ответов на два вопроса, которые у меня есть в конце поста. заранее спасибо. :) - person StudentAccount4; 03.04.2020

Прежде всего: я предпочитаю изменчивый логический флаг, а не isInterrupted(). Это ясно, лаконично и идиоматически установлено. Необходимая структура для 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).

Кроме того: предположим, что ваш класс реализует Runnable и не расширяет Thread, тогда вам также нужно позаботиться о настройке selfPhilosopher в начале run (и нигде больше).

person tastaturtier    schedule 02.05.2020
comment
Я только что видел его. Спасибо, что нашли время написать этот проф :). Рад, что вы посмотрели ссылки, которые я прикрепил в файле :) - person StudentAccount4; 30.06.2020