Error in run() method when using Thread.sleep() - java

I am trying to run an Elevator instance in its own thread. The run() method is being called, but there must be some error in my code that is preventing it from running. My code compiles and runs without errors, but the "Elevator starting up" is never printed.
I think it has to do with Thread.sleep() needing to throw an InterruptedException. I tried to try/catch the exception since Runnable doesn't throw an InterruptedException.
Can you help me figure out why it isn't running?
Here is my run() method:
#Override
public void run() {
System.out.printf("Elevator starting up");
while(true) {
try {
if (currentDirection == Direction.UP) {
this.moveUp();
}
else if (currentDirection == Direction.DOWN) {
this.moveDown();
}
else {Thread.sleep(250);}
}
catch (InterruptedException ie) {
System.out.println("Elevator has experienced a critical error")
}
}
}
Here is my start() method within the Elevator class. This is called from main for each elevator in the building.
public void start() {
activeThread = new Thread();
activeThread.start();
}
The moveUp() method:
public void moveUp() throws InterruptedException {
Thread.sleep(travelSpeed);
setCurrentFloor(currentFloor++);
}
The moveDown() method:
public void moveDown() throws InterruptedException{
Thread.sleep(travelSpeed);
setCurrentFloor(currentFloor--);
}
Full PassengerElevator.class code
public class PassengerElevator implements ElevatorMover, Runnable {
private final int elevID; // elevator number
private final int maxCapacity; // max capacity of the elevator
private int currentCapacity; // the current capacity of the elevator
private final long travelSpeed; // length of travel time between floors
private final long doorSpeed; // length of time door stays open
private int currentFloor; // the current floor the elevator is on
private final int defaultFloor; // the default floor after timeout
private Direction currentDirection; // the current direction the elevator is moving
public Thread activeThread = null; // contains the instance of an elevator thread
/**
* Constructor
* #param elevID the ID number, as an int, given to the elevator
*/
public PassengerElevator(int elevID) {
this.elevID = elevID;
maxCapacity = 10;
currentCapacity = 0;
travelSpeed = 500; // in milliseconds
doorSpeed = 500; // in milliseconds
currentFloor = 1;
defaultFloor = 1;
currentDirection = Direction.IDLE;
}
/**
* makes the elevator go up one floor. Takes travelSpeed time
* #throws InterruptedException
*/
#Override
public void moveUp() throws InterruptedException {
Thread.sleep(travelSpeed);
setCurrentFloor(currentFloor++);
}
/**
* makes the elevator go down one floor. Takes travelSpeed time
* #throws InterruptedException
*/
#Override
public void moveDown() throws InterruptedException{
Thread.sleep(travelSpeed);
setCurrentFloor(currentFloor--);
}
/**
* makes the elevator door open for doorSpeed time. When door is open people
* move into elevator
* #throws InterruptedException
*/
#Override
public void openDoors() throws InterruptedException{
Thread.sleep(doorSpeed);
}
public int getElevID() {
return elevID;
}
private int getMaxCapacity() {
return maxCapacity;
}
private int getCurrentCapacity() {
return currentCapacity;
}
private void setCurrentCapacity(int x) {
currentCapacity = x;
}
private double getTravelSpeed() {
return travelSpeed;
}
private double getDoorSpeed() {
return doorSpeed;
}
public int getCurrentFloor() {
return currentFloor;
}
private void setCurrentFloor(int x) {
currentFloor = x;
}
private int getDefaultFloor() {
return defaultFloor;
}
private void setCurrentDirection(Direction x) {
currentDirection = x;
}
private Direction getCurrentDirection() {
return currentDirection;
}
/**
* Starts a new thread for an elevator instance to run in
*/
public void start() {
activeThread = new Thread();
activeThread.start();
}
/**
* The running loop for an elevator instance. Client will change current direction
* and use the currentFloor as a check.
*/
#Override
public void run() {
System.out.printf("Elevator starting up");
while(true) {
try {
if (currentDirection == Direction.UP) {
this.moveUp();
}
else if (currentDirection == Direction.DOWN) {
this.moveDown();
}
else {Thread.sleep(250);}
}
catch (InterruptedException ie) {
System.out.println("Elevator has experienced a critical error")
}
}
}
}

You are creating a Thread instance directly, and since it is the plain Java Thread class, it has no code in the run method. That means that when you start it, it does nothing. This is the relevant code:
public void start() {
activeThread = new Thread();
activeThread.start();
}
You need to start a thread that is going to run your code. Either make your elevator class extend Thread or implement Runnable.
When extending Thread:
thread = new Elevator();
thread.start();
When implementing Runnable:
thread = new Thread(new Elevator());
thread.start();
The Thread documentation provides examples of usage.

Related

How to make two threads wait and notify each other

I have to create two Threads which have to poll and object from a queue in 2 seconds intervals.
The first Thread poll and object then wait and notify the second one to poll the object from it's queue.
I read all about wait and notify but nothing works with me.
Any sugestions?
First thread:
public class SouthThread extends Thread {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() {
Scanner input = new Scanner(System.in);
for (int i = 0; i < 2; i++) {
Car c = new Car();
System.out.println("Enter registration number: ");
String regNum = input.nextLine();
c.setRegNum(regNum);
q.offer(c);
}
}
public int getQueueSize() {
return q.size();
}
#Override
public void run() {
while (q.size() != 0)
try {
while (q.size() != 0) {
synchronized (this) {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out
.println(" have passed the bridge from the south side.");
this.wait(2000);
notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Second thread:
public class NorthThread extends Thread {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() {
Scanner input = new Scanner(System.in);
for (int i = 0; i < 2; i++) {
Car c = new Car();
System.out.println("Enter registration number: ");
String regNum = input.nextLine();
c.setRegNum(regNum);
q.offer(c);
}
}
public int getQueueSize() {
return q.size();
}
#Override
public void run() {
try {
while (q.size() != 0) {
synchronized (this) {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out
.println(" have passed the bridge from the north side.");
this.wait(2000);
notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main Thread:
public class Main {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
SouthThread tSouthThread = new SouthThread();
NorthThread tNorthThread = new NorthThread();
tSouthThread.CreateQueue();
tNorthThread.CreateQueue();
System.out.println(tSouthThread.getQueueSize());
tSouthThread.start();
tNorthThread.start();
}
}
It seems that what you basically want to achieve is a system that alternates control between two independent units so that each of the units gets some time to process followed by a two second waiting period (or vice versa).
There are two main ways you could achieve this:
Using a central control
With autonomous communicating agents
The first approach is a bit easier. Here, you have a central "master" component which takes care of coordinating who gets the processing time and also implements the wait times. For that approach, the two independent units do not even have to be Threads:
public class South {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() { ... }
public void poll() {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out.println(" have passed the bridge from the South side.");
}
}
public class North {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() { ... }
public void poll() {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out.println(" have passed the bridge from the North side.");
}
}
// This is the "master" class
public class Main {
public static void main(String[] args) {
South south = new South();
North north = new North();
south.CreateQueue();
north.CreateQueue();
boolean done = false;
while (!done) {
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
north.poll();
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
south.poll();
}
}
}
Note that North and South do not inherit from Thread here, i.e., they are just plain old objects.
(However, if your program is more complex and North/South are only one part of it, you might want to make Main(!) a separate thread and put the above while-loop inside the thread's run method, so that the rest of the program can run concurrently.)
In the second approach, you don't have such a central control component, but the both North and South run in their own separate threads. This then requires that they coordinate who's allowed to process by communicating with each other.
public class SouthThread extends Thread {
protected Queue<Car> q = new LinkedList<Car>();
protected North north;
public void CreateQueue() { ... }
public void poll() { ... }
public void run() {
boolean done = false;
while (!done) {
// wait two seconds
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
// process one element from the queue
poll();
// notify the other thread
synchronized (north) {
north.notifyAll();
}
// wait until the other thread notifies this one
try {
synchronized (this) {
wait();
}
} (catch InterruptedException) { /* TODO */ }
}
}
}
public class NorthThread extends Thread {
protected Queue<Car> q = new LinkedList<Car>();
protected South south;
public void CreateQueue() { ... }
public void poll() { ... }
public void run() {
boolean done = false;
while (!done) {
// wait two seconds
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
// process one element from the queue
poll();
// notify the other thread
synchronized (south) {
south.notifyAll();
}
// wait until the other thread notifies this one
try {
synchronized (this) {
wait();
}
} (catch InterruptedException) { /* TODO */ }
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
SouthThread tSouthThread = new SouthThread();
NorthThread tNorthThread = new NorthThread();
tSouthThread.north = tNorthThread;
tNorthThread.south = tSouthThread;
tSouthThread.CreateQueue();
tNorthThread.CreateQueue();
tSouthThread.start();
tNorthThread.start();
}
}
A more general remark: since both North and South seem to be doing basically the same, there's probably no need to implement them in two separate classes. Instead, it should be sufficient to have only one class that implements the desired functionality and instantiate it twice:
// We can combine the functionality of North and South
// in a single class
public class NorthSouth {
public void CreateQueue() { ... }
public void poll() { ... }
// etc.
}
public class Main {
public static void main(String[] args) {
NorthSouth north = new NorthSouth();
NorthSouth south = new NorthSouth();
north.CreateQueue();
south.CreateQueue();
// etc.
}
}
wait and notify must refer to the same lock: When you call object.wait(2000) what you're saying is "I'm going to wait here for 2000 millis, or until someone else calls object.notify() where object refers to me"
I still don't completely understand what you want to achieve, but if you simply want two threads that concurrently do:
Do something
Wait 2 seconds
GOTO 1
then you don't need wait/notify at all, you could get around using Thread.sleep() or potentially two instances of java.util.Timer.
But again, I'm not sure I understand correctly. :-(

Java threads with timing implementation

I have this thread class I am trying to work with.
public class Execution implements Runnable {
public String name;
public double time;
public double timeToDisplay;
public Execution(String name, double et){
this.name = name;
this.time = (et*1000);
}
public void run(){
try{
}catch(Exception e){}
}
/**
* #return the timeToDisplay
*/
public double getTimeToDisplay() {
return timeToDisplay;
}
/**
* #param timeToDisplay the timeToDisplay to set
*/
public void setTimeToDisplay(double timeToDisplay) {
this.timeToDisplay = timeToDisplay;
}
}
I am trying to get the variable timeToDisplay to change every milisecond that the thread runs. The thread is supposed to run for a set amount of et(execution time).
All I need the task to do is run according to the execution time and assign the current time to timeToDisplay Variable.
Here is a sample of a simple scheduled job with comments. Feel free to ask for details.
public class Execution implements Runnable {
public String name;
protected long startedAtMs;
// total timeout in ms
protected long timeoutMs;
// rate: 1 execution per 2 ms
private long rateMs = 2;
// when was the previousExecution
private long prevExecutionMs;
// action to run each 1 ms
protected Runnable action;
public Execution(String name, double et, Runnable action) {
this.name = name;
this.action = action;
this.timeoutMs = (long) (et * 1000);
}
public void run() {
startedAtMs = System.currentTimeMillis();
prevExecutionMs = startedAtMs;
while (true) {
// check if the job was interrupted
if (Thread.interrupted()) {
return;
}
long now = System.currentTimeMillis();
// check if it's time to finish
if (now - startedAtMs > timeoutMs) {
break;
}
// check if it's time to run the action
if(now - prevExecutionMs > rateMs){
// run the action
action.run();
// update the executed time
prevExecutionMs = now;
}
}
}
// this getter could be used to get the running time
public double getTimeToDisplay() {
return (System.currentTimeMillis() - startedAtMs) / 1000D;
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Execution("exec", 0.5, new Runnable() {
#Override
public void run() {
System.out.println(new Date());
}
}));
//starts the thread
thread.start();
//waits to finish
thread.join();
System.out.println("Done!");
}
}
I am not sure that is what you expect, but:
public void run() {
try {
while(true) {
timeToDisplay++;
Thread.sleep(1);
}
} catch (Exception e) {
}
}
You may need to synchronize your get and set methods, depending on what you are trying to achieve.
Thread t1 = new Thread(new Execution(Name1,et1, new Runnable(){
#Override
public void run() {
p1RunningState.setText("Running");
}
}));
t1.start();
if(!(t1.isAlive())){
p1RunningState.setText("Stopped");
}
t1.join();

How to wake up RecursiveTask<V> with notify?

I cannot figure it out, how can I wake up RecursiveTasks, invoked by ForkJoinPool, when these tasks are on hold by wait method. Here is my simple example with the method MainRecursionClass.resume which is incorrect (does not wakes up RecursiveTasks).
public class Program {
public static void main(String[] args) {
Program p = new Program();
final MainRecursionClass mrc = p.new MainRecursionClass();
//Thread outputs integers to simulate work
new Thread() {
public void run() {
mrc.doJob();
}
}.start();
//Thread performs wait and notify on MainRecursionClass object
p.new PauseResume(mrc).start();
}
/**
*
* This class performs suspend and resume operations to the MainRecursionClass class object
*
*/
private class PauseResume extends Thread {
private MainRecursionClass rv;
public PauseResume(MainRecursionClass rv) {
this.rv = rv;
}
#Override
public void run() {
while(!isInterrupted()) {
try {
sleep(4000);
rv.suspend();
sleep(8000);
rv.resume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private class MainRecursionClass {
private boolean pause = false;
private MyRecursive rv;
public void doJob() {
rv = new MyRecursive(0, 100000);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(rv);
}
public void suspend() {
pause = true;
System.out.println("Suspended");
}
/**
* This method is incorrect. It should wake up all MyRecursive instances to continue their work.
*/
public synchronized void resume() {
pause = false;
notifyAll();
System.out.println("Resumed");
}
private class MyRecursive extends RecursiveTask<Object> {
private static final long serialVersionUID = 1L;
private int start;
private int length;
private int threshold = 15;
public MyRecursive(int start, int length) {
super();
this.start = start;
this.length = length;
}
protected void computeDirectly() throws Exception {
for (int index = start; index < start + length; index++) {
//PAUSE
synchronized (this) {
try {
while(pause) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//PAUSE
//some output to simulate work...
System.out.println(index);
Thread.sleep(1000);
}
}
/**
* Recursion
*/
#Override
protected Object compute() {
if (length <= threshold) {
try {
computeDirectly();
} catch (Exception e) {
return e;
}
return null;
}
int split = length / 2;
invokeAll(new MyRecursive(start, split),
new MyRecursive(start + split, length - split));
return null;
}
}
}
}
You should not use wait/notify in the tasks running on a thread pool. If your pool is bounded, then it may cause thread starvation (a form of deadlock). If it is unbounded, too many threads can be created and main memory exhausted.
Instead, you should split your task in 2 (or more) and start subtasks according to their starting conditions. When you want a task to wait(), then refactor it so that current subtask exits, and next subtask is prepared to run.
Finally I came to this solution: I created List<MyRecursive> list = new ArrayList<>(); object in MainRecursionClass and added every MyRecursive instance, created recursively, in the list. The class MyRecursive has new method:
public synchronized void resume() {
notify();
}
When, the method MainRecursionClass.resume(), which wakes up the threads, looks like this:
public void resume() {
System.out.println("Resumed");
pause = false;
for(MyRecursive mr : list) {
if(mr != null)
mr.resume();
}
}
}

Using a jProgressBar with SaxParser

My Problem is solved. Here is the code:
SwingWorker class:
package ths.turnier;
import javax.swing.SwingUtilities;
/**
* This is the 3rd version of SwingWorker (also known as
* SwingWorker 3), an abstract class that you subclass to
* perform GUI-related work in a dedicated thread. For
* instructions on using this class, see:
*
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
*
* Note that the API changed slightly in the 3rd version:
* You must now invoke start() on the SwingWorker after
* creating it.
*/
public abstract class SwingWorker {
private Object value; // see getValue(), setValue()
private Thread thread;
/**
* Class to maintain reference to current worker thread
* under separate synchronization control.
*/
private static class ThreadVar {
private Thread thread;
ThreadVar(Thread t) { thread = t; }
synchronized Thread get() { return thread; }
synchronized void clear() { thread = null; }
}
private ThreadVar threadVar;
/**
* Get the value produced by the worker thread, or null if it
* hasn't been constructed yet.
*/
protected synchronized Object getValue() {
return value;
}
/**
* Set the value produced by worker thread
*/
private synchronized void setValue(Object x) {
value = x;
}
/**
* Compute the value to be returned by the <code>get</code> method.
*/
public abstract Object construct();
/**
* public void run() { finished(); } Called on the event dispatching thread (not on the worker thread)
* after the <code>construct</code> method has returned.
*/
public void finished() {
}
/**
* A new method that interrupts the worker thread. Call this method
* to force the worker to stop what it's doing.
*/
public void interrupt() {
Thread t = threadVar.get();
if (t != null) {
t.interrupt();
}
threadVar.clear();
}
/**
* Return the value created by the <code>construct</code> method.
* Returns null if either the constructing thread or the current
* thread was interrupted before a value was produced.
*
* #return the value created by the <code>construct</code> method
*/
public Object get() {
while (true) {
Thread t = threadVar.get();
if (t == null) {
return getValue();
}
try {
t.join();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // propagate
return null;
}
}
}
/**
* Start a thread that will call the <code>construct</code> method
* and then exit.
*/
public SwingWorker() {
final Runnable doFinished = new Runnable() {
public void run() { finished(); }
};
Runnable doConstruct = new Runnable() {
public void run() {
try {
setValue(construct());
}
finally {
threadVar.clear();
}
SwingUtilities.invokeLater(doFinished);
}
};
Thread t = new Thread(doConstruct);
threadVar = new ThreadVar(t);
}
/**
* Start the worker thread.
*/
public void start() {
Thread t = threadVar.get();
if (t != null) {
t.start();
}
}
}
MonitoredInputStream:
/**
* A class that monitors the read progress of an input stream.
*
* #author Hermia Yeung "Sheepy"
* #since 2012-04-05 18:42
*/
public class MonitoredInputStream extends FilterInputStream {
private volatile long mark = 0;
private volatile long lastTriggeredLocation = 0;
private volatile long location = 0;
private final int threshold;
private final List<ChangeListener> listeners = new ArrayList<ChangeListener>(4);
/**
* Creates a MonitoredInputStream over an underlying input stream.
* #param in Underlying input stream, should be non-null because of no public setter
* #param threshold Min. position change (in byte) to trigger change event.
*/
public MonitoredInputStream(InputStream in, int threshold) {
super(in);
this.threshold = threshold;
}
/**
* Creates a MonitoredInputStream over an underlying input stream.
* Default threshold is 16KB, small threshold may impact performance impact on larger streams.
* #param in Underlying input stream, should be non-null because of no public setter
*/
public MonitoredInputStream(InputStream in) {
super(in);
this.threshold = 1024*16;
}
public void addChangeListener(ChangeListener l) { if (!listeners.contains(l)) listeners.add(l); }
public void removeChangeListener(ChangeListener l) { listeners.remove(l); }
public long getProgress() { return location; }
protected void triggerChanged( final long location ) {
if ( threshold > 0 && Math.abs( location-lastTriggeredLocation ) < threshold ) return;
lastTriggeredLocation = location;
if (listeners.size() <= 0) return;
try {
final ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener l : listeners) l.stateChanged(evt);
} catch (ConcurrentModificationException e) {
triggerChanged(location); // List changed? Let's re-try.
}
}
#Override public int read() throws IOException {
final int i = super.read();
if ( i != -1 ) triggerChanged( location++ );
return i;
}
#Override public int read(byte[] b, int off, int len) throws IOException {
final int i = super.read(b, off, len);
if ( i > 0 ) triggerChanged( location += i );
return i;
}
#Override public long skip(long n) throws IOException {
final long i = super.skip(n);
if ( i > 0 ) triggerChanged( location += i );
return i;
}
#Override public void mark(int readlimit) {
super.mark(readlimit);
mark = location;
}
#Override public void reset() throws IOException {
super.reset();
if ( location != mark ) triggerChanged( location = mark );
}
}
How to use this:
void updateProgressWknAdd(final int i)
{
Runnable doSetProgress = new Runnable() {
public void run() {
progressWknAdd.setValue(i);
}
};
SwingUtilities.invokeLater(doSetProgress);
}
Object doWorkWkn(String pfad) {
// Code which reads file + setting the max of jprogressbar to file size. and:
final MonitoredInputStream mis = new MonitoredInputStream(fis);
mis.addChangeListener( new ChangeListener() { #Override public void stateChanged(ChangeEvent e) {
updateProgressWknRead((int) mis.getProgress());
}});
}
How to use the worker:
SwingWorker worker = new SwingWorker() {
public Object construct() {
return doWorkWkn(pfad_zur_datei);
}
public void finished() {
frame_progressbar.setVisible(false);
}
};
worker.start();
The swingWorker runs doWorkWkn until it's finished. After that a jFrame is set non-visible.
The doWorkWkn() reads the file and adds a changeListener, which updates the progressbar on every change.
Swing is NOT thread safe.
The UI doesn't update because you are blocking the EventDispatchingThread with the reading of the file. This is preventing the progress bar from been updated on the screen.
As #LanguagesNamedAfterCofee suggested, you should use a SwingWorker to perform the actual reading of the file and allow it's update methods (publish and setProgress) to update the UI.
Somewhere in the code you are using you use a diamond operator that is <> You have to resolve this to the matching generic.
Like transform List<String> foo = new ArrayList<>(); to List<String> foo = new ArrayList<String>();
Just search for the <> occurrence and resolve it.

Java, stopping (interrupting) the thread

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

Categories