我正在尝试着名的餐饮哲学家,并且已经完成,但是我很难中断线程。
因此,您知道在这个问题中,我们有5个线程(哲学家),并且用户设置了实验结束的实验时间。
值得注意的是,我在StackOverflow上看到了多个答案。
第一个来自@Konrad Reiche How do you kill a Thread in Java? /Stackoverflow link
在那个特定的帖子中,人们说使用volatile布尔值作为标志可能会奏效,但恐怕练习纸中说我不能使用volatile布尔值来中断线程,但是我可以将其用于其他目的。 (学习练习)。
第二个是Thread interrupt() does not interrupt thread/Stackoverflow link
还没有真正的帮助!。
我将尝试提供必要的代码,希望有人指出我的错误。
在这种尝试中,即使整个实验时间接近20秒,程序也不会停止。并且线程不会被终止也不会被中断。
private volatile Thread selfPhilosopher = this;
@Override
public void stopPhilosopher() {
System.out.printf("\n%s will stop.\n",selfPhilosopher.getName());
selfPhilosopher.interrupt();
}
/*
//Making a synchronized method didnt help either! :(.
private synchronized boolean isStopped(){
return selfPhilosopher.isInterrupted();
}
*/
@Override
public void run() {
while (!selfPhilosopher.isInterrupted()){//selfPhilosopher is a thread equals to this!.
try {
think();
eat();
//selfPhilosopher.sleep(100);//look at (**) at the end of the post!.
} 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());
}
}
}
run()
和stopPhilosopher()
将由教授提供的代码调用,如下所示:
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
philosophers[i].start();
}
Thread.sleep(EXP_DURATION_MS);
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
philosophers[i].stopPhilosopher();
}
哲学家课是公开的,并且扩展了Thread!。
**)在练习中,不需要使线程休眠,但是当我在第二篇提供的帖子中看到有人@ user207421发表“线程仅在可中断操作期间被中断,例如Thread.sleep(),Thread。 wait()和一些I / O调用(不是全部)。”作为无望的尝试,我大声疾呼,但这并没有使它变得更好或更糟,它只是使线程休眠了一段时间。
如果需要,我可以为eat和思考方法提供代码,但我假设您已经知道其中的内容。 :)
当使用像这样的易失性布尔值时起作用:
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()` with
Thread.currentThread()。isInterrupted()didn't solve the problem. yet im getting stopped from the
eat()`方法,但线程似乎像僵尸一样重生:(
为了更好地理解问题,我将在其中添加think()
和eat()
方法,这些方法具有一些将触发run()
中的catch子句的语句
请注意,由于线程永远不会在run()中终止,所以程序是无尽的,这是错误的private void think() throws InterruptedException {
System.out.printf("%s is Thinking.\n",selfPhilosopher.getName());
Thread.sleep(this.random.nextInt(PhilosopherExperiment.MAX_THINKING_DURATION_MS));
}
private void eat() {
System.out.printf("""
%s is trying to eat!.
""",selfPhilosopher.getName() );
table.lock();
try {
if (firstToStartEating){
System.out.printf("%s is the first to eat no and no one has been eating.\n", selfPhilosopher.getName() );
//if first one to eat then no need to check for neighbors!.
firstToStartEating=false;
}else {
//make both neighbors wait after checking if they are not eating!.
System.out.printf("checking if the %s is eating!..->", ((Philosopher) left).getName());
if (((Philosopher) left).getIsEating()) {
((Philosopher) left).getNeighborCondition().await();
}
System.out.printf("%s is is not eating.\n", ((Philosopher) left).getName());
Thread.sleep(random.nextInt(PhilosopherExperiment.MAX_TAKING_TIME_MS));
System.out.printf("checking if the %s is eating!..->", ((Philosopher) right).getName());
if (((Philosopher) right).getIsEating()) {
((Philosopher) left).getNeighborCondition().await();
}
System.out.printf("%s is is not eating.\n", ((Philosopher) right).getName());
}
System.out.printf("%s starting to eat.\n", selfPhilosopher.getName());
this.setIsEating(true);
Thread.sleep(PhilosopherExperiment.MAX_EATING_DURATION_MS);
this.setIsEating(false);
System.out.printf("%s finished eating.\n", selfPhilosopher.getName());
this.getNeighborCondition().signalAll();//notify all that this professor finished eating.
} catch (InterruptedException e) {
System.out.println(selfPhilosopher.getName()+ " was interupted form eat!..\n");
} finally {
table.unlock();
}
}
输出:
Philosopher1 in seat nr: 1 is trying to eat!. Philosopher3 in seat nr: 3 finished eating. checking if the Philosopher3 in seat nr: 3 is eating!..->Philosopher3 in seat nr: 3 is is not eating. checking if the Philosopher5 in seat nr: 5 is eating!..->Philosopher5 in seat nr: 5 is is not eating. Philosopher4 in seat nr: 4 starting to eat. the Philosopher3 in seat nr: 3 is RUNNABLE and is interrupted false. Philosopher3 in seat nr: 3 is Thinking. Philosopher3 in seat nr: 3 is trying to eat!. Philosopher1 in seat nr: 1 will stop. Philosopher2 in seat nr: 2 will stop. Philosopher3 in seat nr: 3 will stop. Philosopher4 in seat nr: 4 will stop. Philosopher5 in seat nr: 5 will stop. Philosopher4 in seat nr: 4 finished eating. checking if the Philosopher4 in seat nr: 4 is eating!..->Philosopher4 in seat nr: 4 is is not eating. checking if the Philosopher1 in seat nr: 1 is eating!..->Philosopher1 in seat nr: 1 is is not eating. Philosopher5 in seat nr: 5 starting to eat. the Philosopher4 in seat nr: 4 is RUNNABLE and is interrupted false. Philosopher4 in seat nr: 4 is Thinking. Philosopher4 in seat nr: 4 is trying to eat!.
我正在尝试与著名的餐饮哲学家合作,并且已经完成,但是我在尝试中断线程方面遇到了很多困难。因此,如您所知,我们有5个线程(...
当引发InterruptedException时,将清除中断标志。这意味着您的循环进行的下一次检查将指示线程未中断,并且线程将继续运行。这就是当您的finally块为中断标志打印出false时所看到的。
在the API doc for the sleep method中对此进行了描述: