//假设有3个车位可以停车,写一个程序模拟多个用户开车离开、停车入库的效果。
//本例使用LOCK来同步线程,Condition来控制线程通信,根据状态(state,0-->3)确定相应的可行操作。
//当车库已满时候,入库车辆需等待;当车库没有车时,无法出库。
//如果不考虑车库中车位的具体地址,只控制车库的数量,可以采用阻塞队列或信号量(Semaphore)实现。
注:如果能将锁应用到车库中车位,而不是锁住整个车库对象,效果会更好。
//Parking:
停车类,包含车库中具体的车位的状态,也是实现入库、离库查找的主要类。
class Parking {
private boolean[] parkingLotsArray;// parking lot status
array.like true,true,true means:3 available spaces. (true:
available; false: not available)
private Lock lock = new ReentrantLock();// lock to
synchronize
private Condition isFree = lock.newCondition();// invoke
isFree.await() when no space; invoke isFree.singal() when space
become available after a car leave parking lot..
private Condition isFull = lock.newCondition();// invoke
ifFull.await() when space is full;invoke isFull.singal() when space
is not full after a parking.
private int state;// 0:no space;1:one space;2:two
space;3:three space
public Parking(int parkingLotNumber) {// init status
this.state = parkingLotNumber;
parkingLotsArray = new boolean[parkingLotNumber];
for (int i = 0; i < parkingLotNumber; i++) {
parkingLotsArray[i] = true;
}
}
// main method for parking.
public void park() {// Consume: park car to free
space
lock.lock();
try {
while (state == 0) {// no space
System.out.println("#Parking#. will isFree.await(). state:" +
state);
isFree.await();
}
// parking car based on free spaces, and a random within the
rage of space. e.g. free space index: {0,2}, if random number is 1,
get second element:2.
Random random = new Random();
List feeSpaceList = getFreeSpace();
int tempIndex = random.nextInt(feeSpaceList.size());
int index = feeSpaceList.get(tempIndex);
System.out.println("#Parking#" +
Thread.currentThread().getName() + "------>
.Parking. index:" + index);
// update status
setFreeSpace(false, index);
state = state - 1;
printParkingLotsArray(true);
// notify
System.out.println("#Parking#. will isFull.notifyAll(). state:"
+ state);
isFull.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
// main method for unparking
public void unpark() {// Produce: move car out of a parking
lot.
lock.lock();
try {
while (state == parkingLotsArray.length) {// full space
System.out.println(".
will isFull.await(). state:" + state);
isFull.await();
}
// 1.unpark car
Random random = new Random();
List parkedSpaceList = getParkedSpace();
int tempIndex = random.nextInt(parkedSpaceList.size());
int index = parkedSpaceList.get(tempIndex);
System.out.println("
" + Thread.currentThread().getName() + ". index:" + index);
// 2.update status
setFreeSpace(true, index);
state = state + 1;
printParkingLotsArray(false);
// 3.notify
System.out.println(".
will isFree.notifyAll();. state:" + state);
isFree.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printParkingLotsArray(boolean flag) {// true:
parking; false:unparking
String temp = null;
if (flag) {
temp = "#Parking#.after a parking.";
} else {
temp = "
unparking--->";
}
temp += (parkingLotsArray[0] + "-->" +
parkingLotsArray[1] + "-->" + parkingLotsArray[2]) +
"";
System.out.println(temp);
}
private List getFreeSpace() {
List list = new ArrayList();
for (int i = 0; i < parkingLotsArray.length; i++)
{
if (parkingLotsArray[i]) {
list.add(i);
}
}
return list;
}
private void setFreeSpace(boolean flag, int index) {
if (index >= parkingLotsArray.length) {
System.out.println("Error. index out of bound");
return;
}
parkingLotsArray[index] = flag;
}
private List getParkedSpace() {
List list = new ArrayList();
for (int i = 0; i < parkingLotsArray.length; i++)
{
if (!parkingLotsArray[i]) {
list.add(i);
}
}
return list;
}
}
class WorkerIn implements Runnable {
private Parking parking;
public WorkerIn(Parking parking) {
this.parking = parking;
}
@Override
public void run() {
while (true) {
parking.park();
}
}
}
class WorkerOut implements Runnable {
private Parking parking;
public WorkerOut(Parking parking) {
this.parking = parking;
}
@Override
public void run() {
while (true) {
parking.unpark();
}
}
}
//Test Case
public class P2_Parking {
public static void main(String[] args) {
Parking parking = new Parking(3);
new Thread(new WorkerOut(parking)).start();
new Thread(new WorkerIn(parking)).start();
}
}