1

Very recently I've asked this question, but wasn unable to fix this. So I have a thread hunter (2 of them actually), who "goes off to catch wild boars". He stores these boars in a container Fridge. He will continue to do so until his working hours expire. However, in case the Fridge is full he has to wait. The aim is to wait until a wild boar is removed from the fridge, but if it takes more then 5 seconds of waiting test must be terminated. So everything works except one thing. After running test and interrupting these threads, the program still continues to run. So how do I completely terminate/stop these threads?

TEST CLASS (main)

class Test {

    public static void main(String[] args) {
        test1();
    }

    public static void test1() {

        Fridge fridge = new Fridge(4);

        Hunter hunter1 = new Hunter("hunter1", 4, fridge);
        Hunter hunter2 = new Hunter("hunter2", 7, fridge);
        Thread hunterThread1 = new Thread(hunter1);
        Thread hunterThread2 = new Thread(hunter2);
        hunterThread1.start();
        hunterThread2.start();

        try { Thread.sleep(1000); } catch (InterruptedException e) {}
        hunterThread1.interrupt();
        hunterThread2.interrupt();
        System.out.println(fridge.getSize());
        System.out.println(hunter1.getWorkTime());
        System.out.println(hunter2.getWorkTime());
    }
}

HUNTER CLASS

class Hunter extends Worker {

    private int workTime;
    private Fridge fridge;

    public Hunter(String name, int workTime, Fridge fridge) {
        super(name);
        this.workTime = workTime;
        this.fridge = fridge;
    }

    public int getWorkTime() {
        return workTime;
    }

    public void run() {
        while (workTime > 0) {
            /** Each hunt takes a random amount of time (1-50 ms) **/
            try { Thread.sleep(workGen()); } catch (InterruptedException e) {}
            /** Add new wild boars **/
            try { fridge.add(new WildBoar()); } catch (InterruptedException e) {}
            workTime--;
            /** If thread is interupted break the loop **/
            if( Thread.currentThread().isInterrupted()){
                break;
            }
        }
    }
}

FRIDGE CLASS

import java.util.Stack;

class Fridge extends Storage {

    private Stack<WildBoar> boars;

    public Fridge(int cap) {
        super(cap);
        boars = new Stack<WildBoar>();
    }

    public int getCap() {
        return cap;
    }

    public int getSize() {
        return boars.size();
    }

    public boolean hasFreeSpace() {
        if ( boars.size() < cap )
            return true;
        else
            return false;
    }

    public synchronized void add(WildBoar boar) throws InterruptedException {
        /** If there's no free space available wait **/
        while ( !hasFreeSpace() ) {
            wait();
        }
        /** Once there's free space available add new item **/
        boars.add(boar);

    }

    public synchronized WildBoar remove() {
        return boars.pop();
    }

}

ADDITIONAL CLASSES FOR COMPILING:

abstract class Worker implements Runnable {

    private String name;

    public Worker(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int workGen() {
        return 1 + (int)(Math.random() * (50 - 1));
    }
}

class WildBoar {

    public WildBoar() {}
}

abstract class Storage {

    protected int cap;

    public Storage(int cap) {
        this.cap = cap;
    }

    public int getCap() {
        return cap;
    }
}
vedran
  • 2,167
  • 9
  • 29
  • 47
  • The given code is not enough to compile it, for instance what is workGen() method in Hunter class. Could you show all relevant code necessary to compile the program? – bbaja42 Dec 20 '11 at 19:55
  • @bbaja42 I added additional classes – vedran Dec 20 '11 at 19:58
  • Also, note that threads will not exit immediately after you try to stop them, but only when check statement ( Thread.isInterrupted) is called. – bbaja42 Dec 20 '11 at 19:58
  • @bbaja42 so how exactly can I stop them? – vedran Dec 20 '11 at 20:04

2 Answers2

4

After you interrupt() the thread which is currently waiting, the native wait method will actually reset the interruption flag. So when you evaluate the isInterrupted() here, it is actually reset and will appear as not interrupted.

if( Thread.currentThread().isInterrupted()){
     break;
}

You will have to re-interrupt the thread after an interruption occurs during the waiting

public synchronized void add(Object boar) {
    /** If there's no free space available wait **/
    while (!hasFreeSpace()) {
     try{
         wait();
     }catch(InterruptedException e){ 
        Thread.currentThread().interrupt(); 
        return; //or rethrow
     }
    }
    /** Once there's free space available add new item **/
    boars.add(boar);
}
John Vint
  • 39,695
  • 7
  • 78
  • 108
3

Currently, the run method in your Hunter thread is discarding interruptions:

try { fridge.add(new WildBoar()); }
 catch (InterruptedException e) {}

Thus, nothing happens when you later check for interruptions

if( Thread.currentThread().isInterrupted()){
    break;
}

To correct this, you need to set the thread's interrupt status:

try { fridge.add(new WildBoar()); }
 catch (InterruptedException e) {
  Thread.currentThread().interrupt();
 }

Summary - ignoring the InterruptedException resets the interrupt status. If you don't or re-throw it or break, then you will need to set the interrupt status manually.

Allen Z.
  • 1,560
  • 1
  • 11
  • 19