Skip to content

Instantly share code, notes, and snippets.

@ciembor
Created January 5, 2012 01:31
Show Gist options
  • Select an option

  • Save ciembor/1563224 to your computer and use it in GitHub Desktop.

Select an option

Save ciembor/1563224 to your computer and use it in GitHub Desktop.
PRIR 06
/*
* autor: Maciej Ciemborowicz
* PRIR 2011/2012
* Uniwersytet Jagielloński
*
*/
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
class Autobusy implements AutobusyI {
CyclicBarrier barrier;
private final static Object lock = new Object();
///////////////////////////////////////////////////////////////////////////////////////////////////
// ________________
// /.--------------.\
// // \\
// // \\
// || .-..----. .-. .--. ||
// ||( ( '-..-'|.-.||.-.|||
// || \ \ || || ||||_||||
// ||._) ) || \'-'/||-' ||
// \\'-' `' `-' `' //
// \\ //
// \\______________//
// '--------------'
// |_|_
// ____ _/ _)_)
// ' | (_)
// .--'"\| ()
// | |
// | |
// |_|
//
private class Stop implements Runnable {
private int passengers;
private double probability;
private Random generator;
private int counter = 0;
public Stop(int passengers, double probability) {
// System.out.println("konstruuję przystanek");
this.passengers = passengers;
this.probability = probability;
this.generator = new Random();
}
@Override public void run() {
// System.out.println("startuję przystanek");
while (true) {
try {
// System.out.println("stop barrier: " + barrier.getNumberWaiting());
barrier.await();
}
catch (Exception e) {
return;
}
// System.out.print(counter);
counter++;
this.generatePassenger();
}
}
public int getPassengers() {
return passengers;
}
private void generatePassenger() {
if (generator.nextDouble() <= probability) {
passengers += 1;
}
}
public boolean letOut() {
if (passengers > 0) {
passengers -= 1;
return true;
}
else {
return false;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// _ ,
// __ __ __ __ __ -- -,_/\\_~0_\ ___ __ __ __
// -- / ___ \- `___`"-,
// --- `"-( @ )----( @ )---`
// '-' '-'
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
private class Road {
private Stop[] positions;
public Road(int length,
int stops_number,
int first_stop_position,
int stop_passengers_number,
double passenger_probability) {
positions = new Stop[length];
this.addStops(first_stop_position,
stops_number,
stop_passengers_number,
passenger_probability);
}
public void startStops() {
for (int i=0; i<positions.length; ++i) {
if (positions[i] != null) {
(new Thread(positions[i])).start();
}
}
}
private int validPosition(int position) {
return Math.abs(position % positions.length);
}
private void addStops(int first_position,
int number,
int passengers,
double probability) {
for (int i=0; i<number; ++i) {
positions[this.validPosition(first_position + (positions.length / number) * i)] =
new Stop(passengers, probability);
}
};
public int nextPosition(int position) {
return validPosition(position + 1);
}
public boolean isStop(int position) {
if (positions[position] != null) {
return true;
}
else {
return false;
}
}
public Stop getStop(int position) {
return positions[position];
}
public int getLength() {
return positions.length;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// _______________________________
// / .-----..--..--..--..--..--..--\
// |)[_____][__][__][__][__][__][___\__
// | _ | -|- _ `\
// _( /.\ | | /.\ [)
// `'---\_/---------------------------\_/--'
//
private class Bus implements Runnable {
private int id, position, capacity, passengers;
private Road road;
private Bus previous;
private Bus next;
private boolean was_empty;
private int counter = 0;
public Bus(int id, Road road, int position, int capacity) {
// System.out.println("konstruuję bus");
this.road = road;
this.position = road.validPosition(position);
this.capacity = capacity;
this.passengers = 0;
this.id = id;
this.was_empty = true;
}
@Override public synchronized void run() {
// System.out.println("startuję bus " + this.id);
while (true) {
try {
// System.out.println("bus" + this.id + " " + "barrier: " + barrier.getNumberWaiting());
barrier.await();
}
catch (Exception e) {
return;
}
// System.out.print(counter);
counter++;
if (road.isStop(position)) {
Stop stop = road.getStop(position);
if (!this.was_empty) {
if (this.passengers > 0) {
this.letOut();
}
if (this.passengers == 0) {
this.was_empty = true;
}
}
else if (this.capacity > this.passengers) {
if (stop.letOut()) {
this.letIn();
}
else {
this.was_empty = false;
this.move();
}
}
else {
this.was_empty = false;
this.move();
}
}
else {
this.move();
}
}
}
private void move() {
// System.out.println("move: " + this.position + " currentpos / nextpos " + road.nextPosition(position));
if (next.getPosition() != road.nextPosition(this.position)) {
position = road.nextPosition(position);
}
}
private boolean letIn() {
if (passengers < capacity) {
passengers += 1;
return true;
}
else {
return false;
}
}
private void letOut() {
passengers -= 1;
}
public void setPrevious(Bus bus) {
this.previous = bus;
}
public void pushNext(Bus bus) {
this.next = bus;
bus.setPrevious(this);
}
public int getPosition() {
return position;
}
public Bus getPrevious() {
return previous;
}
public Bus getNext() {
return next;
}
public int getPassengers() {
return passengers;
}
public int minDistance() {
int previousDistance, nextDistance;
if (this.position > previous.getPosition()) {
previousDistance = this.position - previous.getPosition();
}
else
{
previousDistance = this.position + (road.getLength() - previous.getPosition());
}
if (this.position < next.getPosition()) {
nextDistance = next.getPosition() - this.position;
}
else
{
nextDistance = next.getPosition() + (road.getLength() - this.position);
}
return Math.min(previousDistance, nextDistance);
}
public int getId() {
return this.id;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// ___ __ ___ ____
// / _ \ /_ | |__ \ |___ \
// | | | | | | ) | __) |
// | | | | | | / / |__ <
// | |_| | __ | | __ / /_ __ ___) | __ __ __
// \___/ (__) |_| (__) |____| (__) |____/ (__|__|__)
//
public class Counter implements Runnable {
int value;
boolean request, done;
public Counter() {
// System.out.println("konstruuję counter");
this.value = 0;
this.done = false;
this.request = false;
}
@Override public void run() {
// System.out.println("startuję counter");
while (true) {
synchronized(lock) {
if (this.value > 0 && done == false) {
// System.out.println("%%%%%%" + this.value + " val / done " + done);
try {
// System.out.println("cter barrier: " + barrier.getNumberWaiting());
barrier.await();
}
catch (Exception e) {
return;
}
this.value -= 1;
// System.out.println("value" + value);
}
else if (this.value == 0 && this.request && done == false) {
// System.out.println("#######" + this.value + " val / done " + done);
this.request = false;
// System.out.println("done!");
this.done = true;
try {
lock.wait();
}
catch (Exception e) {
return;
}
}
}
}
}
public boolean done() {
System.out.print("");
return this.done;
}
public void count(int value) {
synchronized(lock) {
this.done = false;
this.request = true;
this.value = value;
lock.notifyAll();
// System.out.println(this.value);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// ()
// JL
// ||
// LJ
// _,--"""""""---.
// ,' `.
// / \
// J L
// F L
// J J
// | J
// ___L______________ J
// /,---------------. "". J
// JJ / \/ | J J
// LL J J | L J
// JJ J # J # | L |
// \\__`.___,_`.____,' F |
// ""-.---------....___/ |
// |_T--+---+--.,._ |
// |--|----\---\-`. |
// |__|____J___J_ F F
// _|__|____|___|_/ L
// | L
// |____________________M-K
//
private Counter counter;
private Road road;
private Bus first_bus;
private int L, K;
///////////////////////////////////////////////////////////////////////////////////////////////////
@Override public void init(int N, int K, int L, int M, double P, int a0, int p0, int pp) {
this.L = L;
this.K = K;
this.barrier = new CyclicBarrier(K+L+1);
// initialization of all Runnable objects
this.counter = new Counter();
this.road = new Road(N, L, p0, pp, P);
this.first_bus = new Bus(0, road, a0, M);
Bus bus = this.first_bus;
for (int i=1; i<K; ++i) {
bus.pushNext(new Bus(i, road, a0 + (i * (N / K)), M));
bus = bus.getNext();
}
bus.pushNext(first_bus);
// start of all Runnable objects
(new Thread(this.counter)).start();
this.road.startStops();
bus = this.first_bus;
for (int i=0; i<K; ++i) {
(new Thread(bus)).start();
bus = bus.getNext();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// uwaga! show wyświetla aktualny stan obiektów, nie czeka na zakończenie tury
// takiego wymogu nie było w specyfikacji
// count czeka na zakończenie tury, dlatego zaleca się uruchomić show po count
@Override public void show() {
int position = 0;
do {
System.out.print(position);
if (road.isStop(position)) {
Stop stop = road.getStop(position);
System.out.print(" P[" + stop.getPassengers() + "]");
}
Bus bus = this.first_bus;
do {
if (bus.getPosition() == position) {
System.out.print(" A[" + bus.getId() + "," + bus.getPassengers() + "]");
}
bus = bus.getNext();
} while (bus != this.first_bus);
System.out.println("");
position += 1;
} while (this.road.validPosition(position) != 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// mam nadzieję, że o to chodziło (w specyfikacji jest to niejasne)
@Override public double calc(int T) {
this.counter.count(T);
int number = 0;
double sum = 0;
Bus bus = this.first_bus;
while (true) {
if (this.counter.done()) {
do {
number += 1;
sum += bus.minDistance();
bus = bus.getNext();
} while (bus.getId() != 0);
break;
}
}
double avg_min_distance = sum/number;
return avg_min_distance;
}
//////////////////////////////////////////////////
public void test(int T) {
for (int i=0; i<1000; ++i) {
this.counter.count(1);
System.out.println("liczę--------------------------------------------");
while (true) {
if (this.counter.done()) {
this.show();
break;
}
}
}
}
////////////////////////////////////////////////
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment