Operating system course design - semaphore mechanism - traffic light simulation
Set up north-south and east-west traffic lights, and then randomly generate any number of cars.
// 南北向和东西向各设置一个交通灯就可以
Light northLight = new Light ( North , Green , 0 ); // 方向,颜色,时间
Light eastLight = new Light ( East , Red , 0 ); // 时间不用指定,因为后面有timeCounter
// 随机生成车辆信息
Car [] cars = new Car [ carNumber ];
Random random = new Random ();
for ( int i = 0 ; i < carNumber ; i ++) { // foreach不行,因为是数组初始化
cars [ i ] = new Car ( random . nextInt ( 4 ), random . nextInt ( timeRange ) + 1 );
// new Car(int direction, int showTime) 随机生成车辆朝向和出现时间,时间范围[1, timeRange]
// 在Car构造函数内部随机生成了车辆ID,即车牌号
}Store the car into the 4-direction queue according to the direction, and the storage order can be from small to large according to the car's appearance time showTime, and it is OK to sort it in a stable and unstable manner, because cars that arrive at the intersection at the same time are no time sequence, and these cars that arrive at the same time are exactly the objects we need to schedule.
// cars数组按车辆出现时间排序的
sortCarsByShowTime ( cars ); private void sortCarsByShowTime ( Car cars []) {
// copy车辆信息
Car [] tmpCars = new Car [ carNumber ];
System . arraycopy ( cars , 0 , tmpCars , 0 , cars . length );
// 对车辆信息按照出现时间排序
int index = 0 ; // 遍历cars数组
for ( int i = 1 ; i <= timeRange ; i ++) { // showTime递增
for ( Car c : tmpCars ) { // 遍历tmpCars
if ( c . getShowTime () == i ) { // 找到showTime=i的车辆
cars [ index ] = c ;
index ++;
}
}
}
} // 车辆信息进队列
Queue < Car > northCarsQueue = new LinkedBlockingQueue <>();
Queue < Car > southCarsQueue = new LinkedBlockingQueue <>();
Queue < Car > westCarsQueue = new LinkedBlockingQueue <>();
Queue < Car > eastCarsQueue = new LinkedBlockingQueue <>();
for ( Car c : cars ) {
switch ( c . getDirection ()) {
case North :
northCarsQueue . add ( c );
break ;
case South :
southCarsQueue . add ( c );
break ;
case West :
westCarsQueue . add ( c );
break ;
case East :
eastCarsQueue . add ( c );
break ;
default :
break ;
}
}
// 集合方式遍历,元素不会被移除
System . out . println ( "生成的车辆信息" );
for ( Car c : northCarsQueue ) System . out . println ( c );
for ( Car c : southCarsQueue ) System . out . println ( c );
for ( Car c : westCarsQueue ) System . out . println ( c );
for ( Car c : eastCarsQueue ) System . out . println ( c );
System . out . println ();The road at a certain moment is a mutually exclusive semaphore, and the influence is reflected in the time when the car actually passes through the intersection.
实际经过时间 >= 到达路口时间
Mutex semaphore definition
// 一条路双向车道,设置2个信互斥信号量集
int [] northMutex = new int [ 100 ];
int [] southMutex = new int [ 100 ];
int [] westMutex = new int [ 100 ];
int [] eastMutex = new int [ 100 ]; /**
* 获取车辆实际经过十字路口的时间
*
* @param roadMutex 道路互斥信号量集
* @param showTime 汽车出现时间
* @param timeCounter 计时器
* @return actualPassTime 车辆实际通过路口的时间
*/
private int getActualPassTime ( int [] roadMutex , int showTime , int timeCounter ) {
// timeCounter-1 确保timeLower落在正确范围内,取商运算
int timeLower = ( timeCounter - 1 ) / lightGreenSeconds * lightGreenSeconds + 1 ; // 时间下界
// 汽车出现时间 < timeLower 重置出现时间,说明汽车等待到下一个绿灯
if ( showTime <= timeLower ) showTime = timeLower ;
if ( roadMutex [ showTime ] == 0 ) { // 该时刻的道路资源未被占用,可通过,直接返回showTime,并将roadMutex[showTime]置1
roadMutex [ showTime ] = 1 ;
return showTime ;
} else { // 这一时刻的道路资源已被占用了,不可通过
int sum = 0 ;
for ( int i = showTime ; i <= timeCounter ; i ++) { // 查询roadMutex数组,看自己排在队列的第几位
if ( roadMutex [ i ] == 1 ) { // =1 表示showTime之后的时刻的道路资源被占用
sum ++;
}
}
roadMutex [ showTime + sum ] = 1 ; // 表示该车占用该一时刻的道路资源
return showTime + sum ; // 返回实际通过时间
}
} int lightGreen ; // 绿灯持续时间,用这个变量,是因为绿灯持续时间是慢慢减少为0的
int timeCounter = 0 ; // 时间计数器,与车辆实际通过路口的时间有关
// 一条路双向车道,设置2个互斥信号量集
int [] northMutex = new int [ 100 ];
int [] southMutex = new int [ 100 ];
int [] westMutex = new int [ 100 ];
int [] eastMutex = new int [ 100 ];
// 4个String存储不同方向的车辆通过信息
String northPassInfo = "" ;
String southPassInfo = "" ;
String westPassInfo = "" ;
String eastPassInfo = "" ;
// 只要还有车,队列就执行
while (! northCarsQueue . isEmpty () || ! southCarsQueue . isEmpty () ||
! westCarsQueue . isEmpty () || ! eastCarsQueue . isEmpty ()) {
// 打印时间段信息 如 1----10s
System . out . print (( timeCounter + 1 ) + "----" + ( timeCounter + lightGreenSeconds ) + "s t " );
// 调度车辆
if ( northLight . getColor () == Green ) { // 南北向车辆通过十字路口
System . out . println ( "南北向绿灯亮n " );
lightGreen = lightGreenSeconds ;
while ( lightGreen -- > 0 ) { // 每经过一辆车花费时间为1,每花费1的时间最多通过2辆车,因为是双向的
timeCounter ++; // timeCounter与车辆实际通过路口的时间有关
northPassInfo += passOneCarInfo ( northCarsQueue , northMutex , timeCounter );
southPassInfo += passOneCarInfo ( southCarsQueue , southMutex , timeCounter );
}
// 打印南北向车辆通过信息
System . out . println ( northPassInfo );
System . out . println ( southPassInfo );
northPassInfo = "" ; // 重置String,循环使用
southPassInfo = "" ;
northLight . setColor ( Red ); // 交通灯颜色转换
eastLight . setColor ( Green );
} else { // 东西向车辆通过十字路口
System . out . println ( "东西向绿灯亮n " );
lightGreen = lightGreenSeconds ;
while ( lightGreen -- > 0 ) { // 每经过一辆车花费时间为1
timeCounter ++;
westPassInfo += passOneCarInfo ( westCarsQueue , westMutex , timeCounter );
eastPassInfo += passOneCarInfo ( eastCarsQueue , eastMutex , timeCounter );
}
// 打印东西向车辆通过信息
System . out . println ( westPassInfo );
System . out . println ( eastPassInfo );
westPassInfo = "" ; // 重置String,循环使用
eastPassInfo = "" ;
eastLight . setColor ( Red ); // 交通灯颜色转换
northLight . setColor ( Green );
}
}PassOneCarInfo
// String存储一辆车的经过信息,便于后面结果的显示
private static String passOneCarInfo ( Queue < Car > carsQueue , int [] roadMutex , int timeCounter ) {
String passInfo = "" ;
if (! carsQueue . isEmpty ()) {
Car car = carsQueue . peek ();
if ( car . getShowTime () <= timeCounter ) { // 假定提前到了,在这一次绿灯亮一定可以穿行
passInfo = car . toString () + "----" + getActualPassTime ( roadMutex , car . getShowTime (), timeCounter ) + " n " ;
carsQueue . remove (); // 满足条件,放行一辆车
}
}
return passInfo ; // 车辆出现信息 + 车辆经过时间
}Set conditions
private static final int timeRange = 20 ; // 模拟总时长
private static final int carNumber = 20 ; // 车辆总数
private static final int lightGreenSeconds = 10 ; // 交通灯显示绿色的时长Generated vehicle information
车牌号 朝向 出现时间
湘U·EM7P6 North 3
赣T·5EYJA North 13
蒙A·2KX51 South 1
黑M·LPHN8 South 7
赣L·5TSL3 South 11
闽P·EWZMH South 11
津G·X1J69 West 2
青F·PXF6N West 12
苏C·L6Z7A West 12
宁A·NTC5J West 13
藏H·6VRJT West 15
浙W·FYWU7 West 15
皖V·2NPLA West 17
川U·LJSYS East 10
桂F·EJEYK East 12
赣S·GMB8C East 15
港J·08QVC East 16
港O·SR58D East 16
台E·1H5IJ East 18
蒙Y·YV5LD East 18
Scheduling results
1----10s 南北向绿灯亮
湘U·EM7P6 North 3----3
蒙A·2KX51 South 1----1
黑M·LPHN8 South 7----7
11----20s 东西向绿灯亮
津G·X1J69 West 2----11
青F·PXF6N West 12----12
苏C·L6Z7A West 12----13
宁A·NTC5J West 13----14
藏H·6VRJT West 15----15
浙W·FYWU7 West 15----16
皖V·2NPLA West 17----17
川U·LJSYS East 10----11
桂F·EJEYK East 12----12
赣S·GMB8C East 15----15
港J·08QVC East 16----16
港O·SR58D East 16----17
台E·1H5IJ East 18----18
蒙Y·YV5LD East 18----19
21----30s 南北向绿灯亮
赣T·5EYJA North 13----21
赣L·5TSL3 South 11----21
闽P·EWZMH South 11----22