Skip to content

Instantly share code, notes, and snippets.

@jiewmeng
Created February 26, 2013 08:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jiewmeng/5036840 to your computer and use it in GitHub Desktop.
Save jiewmeng/5036840 to your computer and use it in GitHub Desktop.
A Parallel Computing Module Assignment done in Java. Simulation of a Client - Server booking system using threads. Clients can book a seat if its available but should ensure that a seat cannot be booked more than once. eg. - Client 1 and 2 gets reservation status and finds that seat 10 is available - They proceeds to book the seat - Only one sho…
package reservation;
public class Request {
public int terminalId;
public String function;
public Object args;
public Request(int terminalId, String function, Object args) {
this.terminalId = terminalId;
this.function = function;
this.args = args;
}
}
package reservation;
import java.util.concurrent.*;
public class ReservationsMain {
public static void main(String[] args) {
BlockingQueue<Request> requests = new ArrayBlockingQueue<Request>(10);
Server server = new Server(requests);
Terminal t1 = new Terminal(1, requests, new ArrayBlockingQueue<Response>(10), server);
Terminal t2 = new Terminal(2, requests, new ArrayBlockingQueue<Response>(10), server);
Terminal t3 = new Terminal(3, requests, new ArrayBlockingQueue<Response>(10), server);
new Thread(server).start();
new Thread(t1).start();
new Thread(t2).start();
new Thread(t3).start();
}
}
package reservation;
public class Response {
public String function;
public Object data;
public Response(String function, Object data) {
this.function = function;
this.data = data;
}
}
package reservation;
import java.util.AbstractMap.SimpleEntry;
import java.util.TreeMap;
import java.util.concurrent.BlockingQueue;
public class Server implements Runnable {
protected TreeMap<Integer, Boolean> reservations;
protected BlockingQueue<Request> requests;
protected TreeMap<Integer, BlockingQueue<Response>> responses;
public Server(BlockingQueue<Request> requests) {
this.requests = requests;
this.responses = new TreeMap<Integer, BlockingQueue<Response>>();
// initialize random data for reservations
reservations = new TreeMap<Integer, Boolean>();
for (int i = 0; i < 20; i++) {
reservations.put(i, (i < 5 ? true : false)); // 0 - 4 booked
}
}
public void connect(int terminalId, BlockingQueue<Response> responseQueue) {
this.responses.put(terminalId, responseQueue);
}
@Override
public void run() {
try {
while (true) {
Request req = requests.take();
switch (req.function) {
case "getReservationStatus":
responses.get(req.terminalId).put(new Response(req.function, this.getReservationStatus()));
break;
case "book":
int seatId = (int) req.args;
SimpleEntry<Integer, Boolean> entry = new SimpleEntry<Integer, Boolean>(seatId, book(seatId));
responses.get(req.terminalId).put(new Response(req.function, entry));
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// returns a copy of reservations
// here its OK to be not synchronized as its a read only thing
public TreeMap<Integer, Boolean> getReservationStatus() {
TreeMap<Integer, Boolean> reservationsCopy = new TreeMap<Integer, Boolean>();
reservationsCopy.putAll(reservations);
return reservationsCopy;
}
// book() is "synchronized" thus only 1 thread can modify it at a time
// a check is done before the actual booking (modification of reservations)
// thus ensuring the seat is not booked by any other in the process
public synchronized boolean book(int seat) {
if (reservations.get(seat) == false) {
reservations.put(seat, true);
return true;
}
return false;
}
}
package reservation;
import java.util.*;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.*;
import java.util.concurrent.*;
public class Terminal implements Runnable {
protected Server server;
protected int terminalId;
protected BlockingQueue<Request> requests;
protected BlockingQueue<Response> responses;
public Terminal(int terminalId, BlockingQueue<Request> requests, BlockingQueue<Response> responses, Server server) {
this.terminalId = terminalId;
this.requests = requests;
this.responses = responses;
this.server = server;
this.server.connect(this.terminalId, this.responses);
}
@SuppressWarnings("unchecked")
@Override
public void run() {
try {
// "simulation" - send requests to server
requests.put(new Request(this.terminalId, "getReservationStatus", null));
requests.put(new Request(this.terminalId, "book", 10));
requests.put(new Request(this.terminalId, "getReservationStatus", null));
requests.put(new Request(this.terminalId, "book", 11));
requests.put(new Request(this.terminalId, "getReservationStatus", null));
requests.put(new Request(this.terminalId, "book", 12));
requests.put(new Request(this.terminalId, "getReservationStatus", null));
while (true) {
Response res = responses.take();
switch (res.function) {
case "getReservationStatus":
TreeMap<Integer, Boolean> reservations = (TreeMap<Integer, Boolean>) res.data;
//System.out.println("getReservationStatus");
for (Entry<Integer, Boolean> reservation : reservations.entrySet()) {
//System.out.println(" - " + reservation.getKey() + " \t " + (reservation.getValue() ? "Booked" : "Available"));
}
break;
case "book":
SimpleEntry<Integer, Boolean> data = (SimpleEntry<Integer, Boolean>) res.data;
System.out.println(terminalId + ": Booking seat " + data.getKey() + " " + (data.getValue() ? "Successful" : "Unsucessful"));
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment