Created
February 26, 2013 08:05
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package reservation; | |
public class Response { | |
public String function; | |
public Object data; | |
public Response(String function, Object data) { | |
this.function = function; | |
this.data = data; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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