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
}
});
}
Related
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).
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() {};
My producer-consumer problem runs perfectly for 1 producer and 1 consumer. It fails to run for 2 producer and 2 consumer. It is reaching some unknown deadlock state. I'm not able to debug. Can anyone please help me with it?
Constraint: One Producer has to produce upto 64 items. And consumer runs until it clears all produced items.
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class Producer implements Runnable {
private static int count = 1;
private Random rg = new Random();
private BlockingQueue<Object> queue = null;
private static int pc = 0;
static int maxPc = 0;
public Producer(BlockingQueue<Object> queue) {
this.queue = queue;
}
#Override
public void run() {
synchronized (queue) {
while(pc <= maxPc) {
try {
produce(pc++);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void produce(int pc) throws InterruptedException {
synchronized(queue) {
while(queue.size() == 8) {
System.out.println(Thread.currentThread().getName() + " : Buffer full: waiting for consumer");
queue.wait();
}
}
synchronized(queue) {
System.out.println("Producer: " + Thread.currentThread().getName() + " adding item "+ pc + " to the queue");
queue.add(pc);
//Thread.sleep(1);
queue.notifyAll();
}
}
}
class Consumer implements Runnable {
private static int consumeCount = 0;
private BlockingQueue<Object> queue = null;
private Random rg = new Random();
public Consumer(BlockingQueue<Object> queue) {
this.queue = queue;
}
#Override
public void run() {
while(true) {
try {
consume();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void consume() throws InterruptedException {
synchronized(queue) {
while(queue.isEmpty()) {
System.out.println(Thread.currentThread().getName() + ": Buffer empty: waiting for producer");
queue.wait();
}
}
synchronized(queue) {
//Thread.sleep(1);
System.out.println("Consumer: "+ Thread.currentThread().getName()+" removing item " + queue.take() + " from the queue");
consumeCount++;
queue.notifyAll();
if(consumeCount == ParallelProcess.maxCC + 1)
System.exit(0);
}
}
}
public class ParallelProcess {
static int maxCC = 0;
int numProducer;
int numConsumer;
private Thread[] cThreads;
private Thread[] pThreads;
private BlockingQueue<Object> queue = null;
public ParallelProcess(int numProducer, int numConsumer, int queueSize) {
this.numProducer = numProducer;
this.numConsumer = numConsumer;
this.queue = new ArrayBlockingQueue<Object>(queueSize);
// create consumer thread objects
cThreads = new Thread[numConsumer];
for (int i = 0; i < numConsumer; i++) {
cThreads[i] = new Thread(new Consumer(queue));
}
// create producer thread objects
pThreads = new Thread[numProducer];
for (int i = 0; i < numProducer; i++) {
pThreads[i] = new Thread(new Producer(queue));
}
}
public void execute() {
// start consumer threads
for (Thread t : cThreads) {
t.start();
}
// start producer threads
for (Thread t : pThreads) {
//System.out.println("tc");
t.start();
}
}
public static void main(String[] args) {
// provide number of producers, number of consumers and the
// max-queue-length
Scanner sc = new Scanner(System.in);
System.out.println("Enter no. of producer and conumer");
int n = sc.nextInt();
ParallelProcess process = new ParallelProcess(n, n, 8);
maxCC = n*64;
Producer.maxPc = maxCC;
process.execute();
// (new Thread()).start();
System.out.println("Thread: " + Thread.currentThread().getName() + " `enter code here`FINISHED");
}
}
First, you should merge synchronized block of the wait and queue.add(pc) to make it automatic, otherwise it might cause some inconstency.
Secondly, you should call queue.notify before wait, otherwise both producer and consumer might be blocked in wait state.
produce method:
public void produce(int pc) throws InterruptedException {
synchronized(queue) {
while(queue.size() == 8) {
System.out.println(Thread.currentThread().getName() + " : Buffer full: waiting for consumer");
queue.notifyAll();
queue.wait();
}
System.out.println("Producer: " + Thread.currentThread().getName() + " adding item "+ pc + " to the queue");
queue.add(pc);
//Thread.sleep(1);
queue.notifyAll();
}
}
consume method:
public void consume() throws InterruptedException {
synchronized(queue) {
while(queue.isEmpty()) {
System.out.println(Thread.currentThread().getName() + ": Buffer empty: waiting for producer");
queue.notifyAll();
queue.wait();
}
System.out.println("Consumer: "+ Thread.currentThread().getName()+" removing item " + queue.take() + " from the queue");
consumeCount++;
if(consumeCount == ParallelProcess.maxCC + 1)
System.exit(0);
}
}
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.
I am still a java newbie and trying to play around learning threads. My question is that it does not loop 5 times. It runs one time and exits. I am using a.class to lock on the class object, such that both the threads are locking on the same object monitor.
class a implements Runnable {
Thread thr;
int count;
String time;
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tick";
System.out.println(time);
notify();
while (time == "Tock") {
wait();
}
}
} catch (Exception e) {
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tock";
System.out.println(time);
notify();
while (time == "Tick") {
wait();
}
}
} catch (Exception e) {
}
}
}
}
}
public class b {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
Here you go, with the original code:
class a implements Runnable {
Thread thr;
int count;
static String time = "Tock";
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
while (time.equals("Tock")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tock";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
while (time.equals("Tick")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tick";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
The problem was that you were calling wait and notify on the implicit this object, when the lock was being held on the a.class object, hence you must call wait/notify on a.class. That was it.
I also did a small restructuring, since I assume you wanted them to print Tick and Tock in an alternating sequence, right?
The answer to why you only loop once is that you call notify() on an object that is not locked and thus an IllegalMonitorStateException is thrown and caught by the empty catch statement.
This is one way to do it. Not saying that it is the best. I tried to keep it close to your code:
public class TickTock {
static final int N = 4;
Object lock = new Object();
int token;
class Worker extends Thread {
int id;
Worker(int id) {
this.id = id;
}
#Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
while (id != token%N) lock.wait();
System.out.println(id + " " + i);
token++;
lock.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void start() {
for (int i = 0; i < N; i++) {
new Worker(i).start();
}
}
public static void main(String[] args) {
new TickTock().start();
}
}
When comparing strings (and objects in general), you should use equals as opposed to == (which is generally reserved for primitives): while(time.equals("Tock")). == on strings will often times result in false when you want it to (and think it should) return true, and hence your loop will exit before expected.