StudentAccount4
StudentAccount4

Reputation: 186

thread is not interruptible

I'm trying to work on the famous dining philosophers and its quite finished but I'm having a quite hard time trying to interrupt threads.

so as you know in this problem we have 5 threads (philosophers) and the user set an experiment time at which the experiment will end.

worth noticing that I looked multiple answers on StackOverflow.

The first one is from @Konrad Reiche How do you kill a Thread in Java? /Stackoverflow link

In that particular post, people have stated that using volatile boolean as a flag might work out but I'm afraid that it is stated in the exercise paper that I cant use the volatile boolean to interrupt a thread but I can use it for other purposes. (studying exercise).

The second one is Thread interrupt() does not interrupt thread/Stackoverflow link

yet nothing really helped!.

I will try to provide the necessary code and I hope someone would just point out my mistake/s. the class Philosopher is public and extends Thread!.

1)First attempt:(might get rejected by the professor if he doesn't want us to use volatile boolean as flag!)

when using volatile boolean like this it works:

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());
        }
    }
}

[UPDATE] on Second attempt:[WORKING]

replacing selfPhilosopher.isInterrupted() with Thread.currentThread().isInterrupted() didn't make any difference as selfPhilosopher=this;

yet I was getting "will stop" from the stopPhilosopher() method but the threads seem to be like zombies keep coming back to life :(

due to the fact that I'm pretty convinced by the opinion of @Konrad Reiche from the first reference provided and the answer of @Nathan Hughes I will stick with using the boolean flag provided by the java isInterrupted() instead of using a volatile flag.

@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();
        }
    }
}

OUTPUT:

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

Upvotes: 1

Views: 333

Answers (2)

tastaturtier
tastaturtier

Reputation: 126

First of all: I favour the volatile boolean flag over isInterrupted(). It is clear, concise and idiomatically established. The necessary structure for isInterrupted() depends more on details (e.g. try/catch in your case because there seems to be a Thread.sleep (or something similar) declaring InterruptedException).

Since try/catch InterruptedException in your example is within the while-loop the interrupt is consumed and need to be resend to selfPhilosopher (which looks a bit dubious). To avoid this put the while-loop into a surrounding 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();
}

The volatile boolean flag would not need resending and could be used in both constellations (while surrounding try/catch as well as while within try).

Additionally: Suppose your class implements Runnable and is not extending Thread then you also need to take care of setting selfPhilosopher at the beginning of run (and nowhere else).

Upvotes: 1

Nathan Hughes
Nathan Hughes

Reputation: 96385

When an InterruptedException is thrown, the interrupt flag is cleared. That means the next check your loop makes will indicate the thread is not interrupted and the thread will keep on running. That's what you're seeing when your finally block prints out false for the interrupt flag.

This is described in 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.

Add this line to the block where you catch an InterruptedException:

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

Upvotes: 1

Related Questions