AsyncEventHandler - Real Time System Java - java

Im trying to make a simulation program in which:
A can is passed on to a conveyor
the can is filled
the can is checked
if the can is damaged, it will be removed from the conveyor
errors:
Exception in thread "RealtimeThread[pri=20,aperiodic]"
java.lang.NullPointerException
at assignment$Sensor.run(assignment.java:99)
at javax.realtime.RealtimeThread$Logic.run(RealtimeThread.java:244)
at javax.realtime.MemoryArea.enter(MemoryArea.java)
at javax.realtime.MemoryArea.enterInternal(MemoryArea.java:1472)
at javax.realtime.RealtimeThread$Logic.run(RealtimeThread.java:230)
I want to use the AsyncEventHandler to trigger a code if the can is damaged but it gives a NullPointerException error if the can is found damaged on the first try however the code works fine if the can is not damaged on the first loop.
import java.util.Random;
import javax.realtime.*;
public class realtime{
AsyncEvent damage;
public static void main(String[] args) {
realtime a = new realtime();
}
public realtime() {
Can can = new Can(1);
Conveyer conveyer = new Conveyer(can);
Sensor Sensor = new Sensor(can);
Grabber grabber = new Grabber(can, Sensor);
ReleaseParameters relConveyer = new PeriodicParameters(new RelativeTime(1000,0));
ReleaseParameters relSensor = new PeriodicParameters(new RelativeTime(1000,0));
conveyer.setReleaseParameters(relConveyer);
Sensor.setReleaseParameters(relSensor);
conveyer.start();
Sensor.start();
damage = new AsyncEvent();
damage.setHandler(grabber);
}
class Can {
int id;
boolean filled;
boolean damaged;
public Can(int id) {
this.id = id;
}
public void isFilled(boolean status) {
this.filled = status; //Print if the Can is filled
}
public void isDamaged(boolean status) {
this.damaged = status;
}
}
class Conveyer extends RealtimeThread {
Can can;
Random random = new Random();
public Conveyer(Can can) {
this.can = can;
}
#Override
public void run() { //While loop can be used to repeat
while(true) {
System.out.println("Can " + can.id + " has entered the conveyer");
System.out.println("Can " + can.id + " is being filled");
can.isFilled(true); //Sleep to give time to fill
System.out.println("Can " + can.id + " is filled");
System.out.println("Can " + can.id + " is being scanned");
can.isDamaged(random.nextBoolean());
try {
waitForNextRelease();
}
catch (Exception e) {}
}
}
}
class Sensor extends RealtimeThread{
Can can;
public Sensor(Can can) {
this.can = can;
}
#Override
public void run() { //While loop can be used to repeat
while(true) {
if(can.damaged) {
System.out.println("Can " + can.id + " is Damaged!");
damage.fire();
} else {
System.out.println("Can " + can.id + " is moved to Stage 2");
}
try {
waitForNextRelease();
}
catch (Exception e) {}
}
}
}
class Grabber extends AsyncEventHandler {
Can can;
RealtimeThread rtt;
boolean damaged = false;
public Grabber(Can can, RealtimeThread rtt) {
this.can = can;
this.rtt = rtt;
}
public void handleAsyncEvent() {
System.out.println("Can " + can.id + " is disposed");
}
}
}

You do not have a default constructor for your Can class. So in your Conveyor class you have Can can; This probably gives you the NullPointerException. Just add another constructor to your Can class like so:
public Can() {};

Related

Java Concurrent: trying to identify my passengers are from which flight

I am trying to figure out the passengers' disembark and embark methods in my project. The problem is the passengers' count will not be in order and I couldn't figure out which flights are ongoing those disembark and embarking actions.
Objective: To figure out the way to add the flight number for passengers.
package airport_ccp;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class airport_CCP {
public static void main(String[] args) {
Random rand = new Random();
Passengers passsenger = new Passengers();
//runway only got one, two gates
//runway is exclusive event, remain inclusive event for gates only
//gates available: 2, so create blockingqueue<runway>(2)
BlockingQueue<Gate> gates = new ArrayBlockingQueue<Gate>(2);
//threadpool for aircraft, two gates available
//so create a fixed threadpool for gates with 2 maximum
ExecutorService threadpool = Executors.newFixedThreadPool(2);
// 2 active inbound for 2 gates.
for (int i = 1; i <= 2; i++) {
gates.add(new Gate(i));
}
//10 flights
for(int i = 1; i <= 10; i++) {
try {
// 3 secnonds hold for new aircraft
Thread.sleep(rand.nextInt(3000));
threadpool.submit(new Aircraft(i, "land", gates));
//initial thought of input
ExecutorService executor = Executors.newCachedThreadPool();
for(int j=0; j<50; j++){
executor.submit(new Runnable() {
public void run() {
Passengers.getInstance().run();
}
});
}
executor.shutdown();
//input ends
} catch (InterruptedException e) {
e.printStackTrace();
}
}
threadpool.shutdown();
try {
if (threadpool.awaitTermination(100, TimeUnit.SECONDS)) {
for (int i = 1; i <= 2; i++) {
gates.take().printReport();
}
}
} catch (InterruptedException e) {
}
}
}
Below is my passenger class
package airport_ccp;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class Passengers {
private static Passengers instance = new Passengers();
private Semaphore sema = new Semaphore(50, true); //set max to 50
private int passengercount = 0;
private Passengers() {
}
public static Passengers getInstance(){
return instance;
}
public void run() {
try {
sema.acquire();
System.out.println( "MH " /*ID input*/ + " : Passengers " + passengercount + " Disembarking");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
try {
dorun();
}
finally {
System.out.println( "MH " /*ID input*/ + " : Passengers " + passengercount + " Embarking");
sema.release();
}
}
public void dorun() {
synchronized (this) {
passengercount++;
}
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
synchronized (this) {
passengercount--;
}
}
}
Aircraft class if there's any concern
package airport_ccp;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class Aircraft implements Runnable{
String status;
int ID;
Date arrival;
BlockingQueue<Gate> gatescount = null;
Gate gate;
public Aircraft(int ID, String status, BlockingQueue<Gate> gatescount) {
this.ID = ID;
this.gatescount = gatescount;
System.out.println("\t Time : " + java.time.LocalDateTime.now() + "\t" + " MH " + ID + " is calling for landing.");
}
#Override
public void run() {
try {
this.status = "land";
gate = gatescount.take();
System.out.println("\t MH " + ID + " has been assigned to " + gate.getName() + ".");
System.out.println( "\t Time : " + java.time.LocalDateTime.now() + "\t" + " MH " + ID + " is " + status + ".");
//Thread.sleep(1000*(1+new Random().nextInt(10)));
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
gate.inc(status);
this.status="depart";
System.out.println("\t Time : " + java.time.LocalDateTime.now() + "\t" + "MH " + ID + " has " + status);
gatescount.add(gate);
}
Err - why do you not pass in the flight number into the run method?
// in Passengers
public void run(int id) {
try {
sema.acquire();
System.out.println( "MH " + id + " : Passengers " + passengercount + " Disembarking");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
try {
dorun();
}
finally {
System.out.println( "MH " + id + " : Passengers " + passengercount + " Embarking");
sema.release();
}
}
// when calling Passengers: pass in that ID
for(int i = 1; i <= 10; i++) {
try {
/* ... */
for(int j=0; j<50; j++){
int id = i; // <-- copy to a constant value; once assigned, id is never changed
executor.submit(new Runnable() {
public void run() {
Passengers.getInstance().run(id);
}
});
}
/* ... */
Note that the previous version used this code, which produces an error because the value of i changes in each iteration, while Java needs to ensure that it stays constant; using a reference that does not change (as above) solves the problem:
for(int j=0; j<50; j++){
executor.submit(new Runnable() {
public void run() {
Passengers.getInstance().run(i); // <-- fails, because i is not, and cannot be made, final
}
});
}

This will compile correctly however it says there is nothing to run in two different IDE

This will compile correctly however it says there is nothing to run in two different IDE. What seems to be the issue here. I have added lines to just print hi to troubleshoot but still nothing.
import java.util.concurrent.*;
//Creates class
public class project42 {
static class ExThread extends Thread {
//Variables are set
Semaphore sema;
String theName;
//
public ExThread(Semaphore sema, String theName) {
super(theName);
this.sema = sema;
this.theName = theName;
}
public void run() {
//test For Westbound
if (this.getName().equals("Westbound Cars")) {
try {
System.out.println(theName + " are waiting");
sema.acquire();
System.out.println(theName + " are attempting");
for (int i = 1; i < 6; i++) {
System.out.println("Westbound: " + i + " is waiting");
Thread.sleep(1000);
System.out.println("Westbound: " + i + " has crossed");
Thread.sleep(1000);
}
} catch (InterruptedException exc) {
System.out.println(exc);
}
System.out.println(theName + " has crossed the bridge");
sema.release();
} else {
//Test for eastbound
System.out.println(theName + " are waiting");
try {
System.out.println(theName + " are waiting");
sema.acquire();
System.out.println(theName + " are attempting");
for (int i = 1; i < 6; i++) {
System.out.println("Eastbound " + i + "is crossing");
Thread.sleep(1000);
System.out.println("Eastboud " + i + " is crossed");
Thread.sleep(1000);
}
} catch (InterruptedException exc) {
System.out.println(exc);
}
System.out.println(theName + " have crossed the bridge");
sema.release();
}
}
//main class
public static void main(String[] args) throws InterruptedException {
System.out.print("hi");
Semaphore sema = new Semaphore(1);
//creates cars
ExThread et1 = new ExThread(sema, "Westbound Cars");
ExThread et2 = new ExThread(sema, "WEastbound Cars");
//runs program
et1.start();
et2.start();
et1.join();
et1.join();
}
}
}
There is nothing to run, since your main is in the inner class (ExThread). It needs to be in the outer class (project42).

How do I get an identical value from two threads calling on the same variable?

I have a program that starts by creating a GUI to handle user input and display the output.
The first thing that happens is the window is created and then the Functions Class method initServer() is called to initialize some variables for the input and output portion
private JFrame frame;
public static Functions func = new Functions();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
Thread.currentThread().setName("Console");
System.out.println(Thread.currentThread().getName() + " [" + Thread.currentThread().getId() + "] Started");
try {
Console window = new Console();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
func.initServer();
}
});
}
With the Functions Class method initServer() being called, We start the process then follow by initializing the i/o variable that will handle all the streams being used to communicate with the process. Then we start the two threads - ConsoleInputWriter and ConsoleOutputReader - responsible for handling Input and Output to the process.
public class Functions {
private ConsoleOutputReader cor = new ConsoleOutputReader();
private ConsoleInputWriter ciw = new ConsoleInputWriter();
private OutputStreamWriter osw;
private InputStreamReader isr;
private BufferedWriter bw;
private BufferedReader br;
private BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
private File serverJar;
private String serverPath;
private ProcessBuilder builder;
private Process proc;
private boolean init = false;
public void initServer()
{
updateConsole("Server Initiated Status: " + serverStatus());
builder = new ProcessBuilder("/bin/bash");
try {
proc = builder.start();
} catch (IOException e) {
e.printStackTrace();
}
osw = new OutputStreamWriter(proc.getOutputStream());
bw = new BufferedWriter(osw);
isr = new InputStreamReader(proc.getInputStream());
br = new BufferedReader(isr);
serverStatus(true);
updateConsole("Server Initiated Status: " + serverStatus());
cor.start();
ciw.start();
}
public String recieveInput()
{
String s = null;
try {
s = input.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
public boolean serverStatus()
{
return init;
}
public void serverStatus(boolean status)
{
init = status;
}
public void exec(String cmd)
{
try {
bw.write(cmd);
bw.newLine();
bw.flush();
} catch (IOException e) {
updateConsole("Cant run: [" + cmd + "] :::::::: " + e);
e.printStackTrace();
}
}
public void updateConsole()
{
//edit to print to textPane
try {
System.out.println(br.readLine());
} catch (IOException e) {
}
}
public void updateConsole(String s)
{
System.out.println(s);
}
public File getJar(/**String s**/)
{
serverJar = new File(Functions.class.
getResource("CraftBukkit.jar").getPath());
return serverJar;
}
public void setPath(String s)
{
serverPath = s;
}
public String getPath()
{
return serverPath;
}
}
Once called the Class ConsoleOutputReader starts and executes a command for the process to start a Jar File and confirms that the i/o streams have been initialized before it tries to get any output. If it continues to the while loop we should be getting output.
public class ConsoleOutputReader extends Thread{
private static Functions func = new Functions();
public void run()
{
currentThread().setName("cor");
System.out.println(currentThread().getName() + " [" + Thread.currentThread().getId() + "] Started");
func.exec("cd " + "~/Desktop/Bukkit" + " && java -Xmx1024M -jar " + func.getJar() + " -o true");
while(func.serverStatus())
func.updateConsole();
}
}
and the Class ConsoleInputWriter follows right after ConsoleOutputReader also confirming that the serverInit() boolean is true, then to wait in a while loop for an input from the user.
public class ConsoleInputWriter extends Thread{
public static Functions func = new Functions();
public void run()
{
currentThread().setName("ciw");
func.updateConsole(currentThread().getName() + " [" + Thread.currentThread().getId() + "] Started");
while(func.serverStatus())
func.exec(func.recieveInput());
}
}
The main issue I have is that with minimal knowledge on threads I seemed to have made the serverStatus() boolean from the Functions class equal two different things. where the output from ConsoleOutputReader is true and the output from ConsoleInputWriter is false. How would I make sure that when I start both threads they're seeing the same value when they call the method?
I've gotten this code to work with two threads where the main thread ran the inputs and a second thread was used to run the outputs, but I wanted to try it setup like this.
Any tips to my style and or patterns I use are also very welcome.
Edit: I realized with all my frantic changes that whatever class calls initServer() is that class that get true when they call serverStatus().
Any methods that change an object for both threads need to be synchronized. When the method runs, if the object is being read by one or both of the threads while it changes, The threads could read different values.
e.x.:
public static synchronized void initServer(boolean bool) { init = bool; }

Why doesnt my ReaderWriter solution work ? (java, concurrency)

So lately i ve been trying to wrap my head around concurrency. And currently I m trying to find a solution for the ReaderWriter Problem.
I got a class File, it counts the number of Readers/Writers and has two Semaphores.
When a Reader tries to read it has to wait as long as there is a Writer Thread writing. When it enters readCount gets incremented within the readerSemaphore
& decremented within the same Semaphore when it leaves.
When a Writer tries to enter it has to wait for as long as there is more than one reader. When it enters it aquires the writerSemaphore and increaese the writerCount. When it leaves it releases the Semaphore.
For some reason that I cant figure out the Writers are not editing the String file in class File.
Thanks in advance :)
public class Main {
public static void main(String[]args) {
File file = new File("1. Chapter: ");
Writer w1 = new Writer(file, " w1 ");
Writer w2 = new Writer(file, " w2 ");
Reader r1 = new Reader(file);
Reader r2 = new Reader(file);
Reader r3 = new Reader(file);
Reader r4 = new Reader(file);
Reader r5 = new Reader(file);
w1.start();
w2.start();
r1.start();
r2.start();
r3.start();
r4.start();
r5.start();
try {
w2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-> Final output: " + file.file);
}}
public class File {
public String file;
private int readCount;
private int writeCount;
private Semaphore semReader;
private Semaphore semWriter;
public File(String file) {
this.file = file;
readCount = 0;
writeCount = 0;
semReader = new Semaphore(1);
semWriter = new Semaphore(1);
}
public synchronized void startReading() {
try {
while(writeCount == 1) {
Thread.currentThread().wait();
}
semReader.acquire();
readCount++;
semReader.release();
System.out.println(" --- File was read");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized String endReading() {
String temp = file;
try {
semReader.acquire();
readCount--;
semReader.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
return temp;
}
public synchronized void startWriting(String edit) {
try {
while(readCount > 0) {
Thread.currentThread().wait();
}
semWriter.acquire();
writeCount++;
System.out.println(" --- File got edited");
file = file + "hi";
}
catch (Exception e) {
}
}
public synchronized void endWriting() {
writeCount--;
semWriter.release();
}}
public class Writer extends Thread {
private File file;
private String edit;
public Writer(File file, String edit) {
this.file = file;
this.edit = edit;
}
#Override
public void run() {
Random rand = new Random();
try {
sleep(1000);
System.out.println(">W: " + Thread.currentThread().getName() + " started first write.");
file.startWriting(" first" + edit);
sleep(3000);
System.out.println(">W: " + Thread.currentThread().getName() + " ended first write.");
file.endWriting();
sleep(2000);
System.out.println(">W: " + Thread.currentThread().getName() + " started second write.");
file.startWriting(" second" + edit);
sleep(3000);
System.out.println(">W: " + Thread.currentThread().getName() + " ended second write.");
file.endWriting();
System.out.println(">W: " + Thread.currentThread().getName() + " finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}}
public class Reader extends Thread {
private File file;
public Reader(File file) {
this.file = file;
}
#Override
public void run() {
Random rand = new Random();
try {
sleep(rand.nextInt(2000));
System.out.println(">R: " + Thread.currentThread().getName() + " startet first read.");
file.startReading();
sleep(3000);
System.out.print(">R: " + Thread.currentThread().getName() + " ended first read: ");
System.out.println(file.endReading());
sleep(rand.nextInt(2000));
System.out.println(">R: " + Thread.currentThread().getName() + " startet second read.");
file.startReading();
sleep(3000);
System.out.print(">R: " + Thread.currentThread().getName() + " ended second read: ");
System.out.println(file.endReading());
System.out.println(">R: " + Thread.currentThread().getName() + " finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}}
Edit:
Thread.currentThread().wait() was wrong.
Waiting on threads is discouraged in the java docs.
Thanks, #JB Nizet for helping me.

Dining philosophers - I spoke to all, just one listens

I'm implementing dining philosophers problem and I faced a problem myself, I do not know what's the cause, hence I am here.
It is after dinner when I'm telling them to leave, I want to force them to create reports cause that's the next stage of their lifetime. When I do so, all respond, but only one acts:
Console Output:
0 >> I was told to stop.
1 >> I was told to stop.
2 >> I was told to stop.
3 >> I was told to stop.
4 >> I was told to stop.
philosopher 0 reporting
report filed, total 1
This is Philosopher class:
import java.util.ArrayList;
import java.util.List;
public class Philosopher implements Runnable {
// 1 - eating
// 2 - thinking
// 3 - waiting
// 4 - reporting
private int id;
private int state;
private int eating;
private int waiting;
private int thinking;
private int consecutiveWaitingTime;
private long thinkingTime;
private long initialDelay;
private long eatingTime;
private long waitingTime;
private boolean thePartyIsOn;
private boolean leftInHand;
private boolean rightInHand;
private boolean speech = false;
private boolean timeLineLogSent = false;
private DiningRoom host;
private Fork left;
private Fork right;
private List<LogBookRecord> timelineLog;
public Philosopher(int idn, DiningRoom host){
timelineLog = new ArrayList<LogBookRecord>();
this.host = host;
thePartyIsOn = true;
leftInHand = false;
rightInHand = false;
thinkingTime = 100l; //miliseconds
eatingTime = 300l;
waitingTime = 50l;
initialDelay = idn*70;
consecutiveWaitingTime = 0;
eating = 0;
waiting = 0;
thinking = 0;
state = 3;
id = idn;
}
#Override
public void run(){
if(speech){ System.out.println("philosopher " +id+ "!"); }
while(thePartyIsOn){
try { Thread.sleep(initialDelay); }
catch (InterruptedException e) { e.printStackTrace(); }
log("Started dining with delay of " +initialDelay+ " miliseconds...");
while(true){
switch(state){
case 1: // eating
if(speech){ System.out.println("philosopher " +id+ " eating"); }
log("Eating...");
eating++;
try { Thread.sleep(eatingTime); }
catch (InterruptedException e) { e.printStackTrace(); }
releaseForks();
state = 2;
break;
case 2: // thinking
if(speech){ System.out.println("philosopher " +id+ " thinking"); }
log("Thinking...");
thinking++;
try { Thread.sleep(thinkingTime);}
catch (InterruptedException e1) { e1.printStackTrace(); }
state = 3;
break;
case 3: // waiting
if(speech){ System.out.println("philosopher " +id+ " waiting"); }
tryEating();
log("Waiting...");
waiting++;
if(consecutiveWaitingTime > 20 && !host.isStarvationAlertOn()){
host.pressStarvationAlertButton(id);
}
try { Thread.sleep(waitingTime); }
catch (InterruptedException e) { e.printStackTrace(); }
break;
case 4: // reporting
if(!timeLineLogSent){
System.out.println("philosopher " +id+ " reporting");
log("Creating final report...");
host.fileReport(id, timelineLog);
timeLineLogSent = true;
thePartyIsOn = false;
}
break;
}
}
}
if(speech){ System.out.println("PHILOSOPHER " +id+ ": My task is done. Good bye."); }
}
private void tryEating() {
if(!leftInHand){ left.take(); leftInHand = true; }
else if(!rightInHand){ right.take(); rightInHand = true;}
else{ state = 1; }
}
private void releaseForks() {
left.release();
leftInHand = false;
right.release();
rightInHand = false;
}
private void log(String log){ timelineLog.add(new LogBookRecord(System.nanoTime(), ("PHILOSOPHER " +id+ ": " +log))); }
public synchronized void reportTime(){
System.out.println(id+ " >> I was told to stop.");
log("I was told to stop!");
log("eating: " +eating);
log("waiting: " +waiting);
log("thinking: " +thinking);
state = 4;
}
public void setLeftFork(Fork fl) { left = fl; }
public void setRightFork(Fork fr){ right = fr; }
}
DiningRoom class:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import utilities.FileHandler;
public class DiningRoom {
private String filename = "PhilosophersFeastReport.txt";
Philosopher[] guests;
Fork[] forks;
private int guestsQty = 5;
private int guestsLeftTheBuilding;
public boolean starvationAlert;
private List<LogBookRecord> diningRoomLog;
private FileHandler fh;
private int reportsFiled;
private long napTime;
private boolean timeIsUp;
Timer timer;
int secondsLeft = 5;
public DiningRoom(){
timeIsUp = false;
timer = new Timer();
napTime = 500l;
m("Constructing the dining room...");
reportsFiled = 0;
guestsLeftTheBuilding = 0;
diningRoomLog = new ArrayList<LogBookRecord>();
m("Creating file for the report...");
fh = new FileHandler();
fh.createFile(filename);
m("File [" +filename+ "] created...");
starvationAlert = false;
m("The guests are in...");
guests = new Philosopher[guestsQty];
forks = new Fork[guestsQty];
m("Assigning forks...");
prepareTheScene(guests,forks);
m("Starting threads...");
oficiallyStartTheDinner(guests);
relax();
}
private void oficiallyStartTheDinner(Philosopher[] phs) {
timer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run() {
secondsLeft--;
m(secondsLeft+ " seconds left...");
if(secondsLeft <= 0){
timeIsUp = true;
this.cancel();
}
}
}, 1000, 1000);
for(Philosopher p : phs){
Thread t = new Thread(p);
t.start();
}
}
private void prepareTheScene(Philosopher[] table, Fork[] cutlery){
m("Preparing the scene...");
Fork f0 = new Fork();
Philosopher ph0 = new Philosopher(0,this);
Fork f1 = new Fork();
Philosopher ph1 = new Philosopher(1,this);
Fork f2 = new Fork();
Philosopher ph2 = new Philosopher(2,this);
Fork f3 = new Fork();
Philosopher ph3 = new Philosopher(3,this);
Fork f4 = new Fork();
Philosopher ph4 = new Philosopher(4,this);
ph0.setRightFork(f0);
ph0.setLeftFork(f1);
ph1.setRightFork(f1);
ph1.setLeftFork(f2);
ph2.setRightFork(f2);
ph2.setLeftFork(f3);
ph3.setRightFork(f3);
ph3.setLeftFork(f4);
ph4.setRightFork(f4);
ph4.setLeftFork(f0);
table[0] = ph0;
table[1] = ph1;
table[2] = ph2;
table[3] = ph3;
table[4] = ph4;
cutlery[0] = f0;
cutlery[1] = f1;
cutlery[2] = f2;
cutlery[3] = f3;
cutlery[4] = f4;
}
private void relax(){
boolean j = true;
boolean k = true;
while(reportsFiled != 5 && guestsLeftTheBuilding != 5){ // to be changed for correct conditions
if(!timeIsUp){
try {
Thread.sleep(napTime);
m("ZzZzZzZz...");
}catch (InterruptedException e) {
e.printStackTrace();
}
if(j){ m("\tManagement is relaxing now..."); j = false; }
if(timeIsUp){
if(k){ tellTheGuestsItIsTimeToGo(); k = false;}
//break;
}
}
}
m("Sorting the report log");
Collections.sort(diningRoomLog);
List<String> readyList = prepareTheList(diningRoomLog);
m("Calling file parser...");
fh.writeToFile(filename, readyList);
m("All done");
}
private List<String> prepareTheList(List<LogBookRecord> log) {
m("Converting the log for file parser...");
List<String> l = new ArrayList<String>();
for(LogBookRecord lbr : log){
l.add(lbr.toString());
}
return l;
}
private void tellTheGuestsItIsTimeToGo() {
for(Philosopher p : guests){
p.reportTime();
}
}
public static void main(String[] args){
new DiningRoom();
}
public synchronized void fileReport(int philosopherId, List<LogBookRecord> report){
diningRoomLog.add(new LogBookRecord(System.nanoTime(), "DINING ROOM: PHILOSOPHER " +philosopherId+ " filed a report"));
diningRoomLog.addAll(report);
reportsFiled++;
m("report filed, total " +reportsFiled);
}
public synchronized void philosopherLeaving(int philosopherId){
diningRoomLog.add(new LogBookRecord(System.nanoTime(), "PHILOSOPHER " +philosopherId+ " just left."));
}
public synchronized boolean isStarvationAlertOn(){ return starvationAlert; }
public synchronized void pressStarvationAlertButton(int starvingPhilosopherId){
diningRoomLog.add(new LogBookRecord(System.nanoTime(), "**** Philosopher "+starvingPhilosopherId+ " raised starvation alert!"));
tellTheGuestsItIsTimeToGo();
m("Philosopher " +starvingPhilosopherId+ " flipped starvation alert...");
}
private void m(String s){ System.out.println(s); }
}
I hacked up your code so it would run and then ran a debugger on it. You have two problems. The first is that you don't actually implement the Dinning Philosopher's algorithm. You just try to take the lock (Fork) without any checks or release algorithm. In my debugger at least two threads were stuck in tryEating(), both were stuck waiting for locks that would never be released.
// broken: no checks before taking lock
private void tryEating() {
if(!leftInHand){ left.take(); leftInHand = true; }
else if(!rightInHand){ right.take(); rightInHand = true;}
else{ state = 1; }
}
Those two variables, leftInHand and rightInHand are instance variables. They only check whether you have the lock. They don't check whether another philosopher has the lock.
The second problem is that you have a "while(true)" in the middle of your event loop, preventing any thread from actually exiting.
while(thePartyIsOn){
try { Thread.sleep(initialDelay); }
catch (InterruptedException e) { e.printStackTrace(); }
log("Started dining with delay of " +initialDelay+ " miliseconds...");
while(true){ // <<-- oops
switch(state){
I think your problem is here in officiallyStartTheDinner :
for(Philosopher p : phs){
Thread t = new Thread(p);
t.start();
}
You never wait for your threads to finish. Once your main program exits, the threads will die because they are not daemon threads. You might be better off using an ExecutorService to execute the runnables from a fixed-size pool of threads. Then you can shutdown() and awaitTermination(...) to allow the threads to complete their tasks.

Categories

Resources