------- android培训、java培训、期待与您交流!----------
看完了张老师的交通管理灯系统,感觉编程最重要的是思路,技术时刻在更新,不会的可以查询API文档。
从这个案例中学到的是面向对象编程的经验和线程池的操作。
交通管理灯系统共包含4个类:
Lamp,Road,LampController与Main函数。
先来分析一下为什么要建立这些类:
交通管理灯系统所包含的元素有3个:交通灯,道路,车辆。
其中题目说忽略具体的车辆,那么车辆就可以看做是一个字符串,我们只是要一个数字,而车辆的数字应该从哪里获得呢?
车辆在等待交通灯的时候都是停在自己的道路上,所以车辆的数字是属于道路的,所以道路这个类应该包含操作车辆数量的方法,包括增和减。车辆增加和减少有的时候是要同时进行的,所以盛放车辆数量的容器应该是一个可变长度的字符串集合,我们可以选择ArrayList。看到“同时进行”,我们就要考虑多线程了。增加是很简单的,可以看做是一个线程,这个线程每隔一个随机的时间后就向List集合添加一辆车;车辆的减少也可以创建一个线程,每隔1秒就检查车辆所在的是否为绿灯,是就利用remove方法去掉这辆车,并返回去掉的这辆车。这样就可以为12条线路都分别创建这两个线程。
至于交通灯以为数量和名称都是固定的,而且具备的方法都是一样的,所以可以将交通灯看做是一个枚举,这个枚举包含绿灯亮、绿灯灭(即红灯亮)以及获得绿灯状态这三个方法。
具体的实现请看代码:
//交通灯的亮灭是有自身决定的,所以它本身就得就有开灯,关灯和判断等是否亮的方法
public enum Lamp {
/*每个枚举都表示一个方向的交通灯,忽略右转方向的灯,就剩下了8盏灯,这把盏灯分为横向和纵向的
* 先看纵向上的,就是南北方向上的,这个方向上又有4盏灯,其中2盏直行灯,2盏左拐灯,这样就可以
* 把它们分为2组了。
* 横向的的也是一样的,所以就可以把这8盏灯分为4组了。
*/
//这是一个循环,包括了8盏灯,从S2N开始亮最后又回到了S2N,具体参数看构造函数
S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
// 为什不直接写Lamp的类型N2S,而是写作字符串"N2S"?因为在使用N2S之前必须先定义好它,但是他在后面
N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false);
private boolean lighted;//等是否亮的标准位
private String next; //当一组等灭的时候他的下一组灯
private String opposite; //就是功能相同的一组等,对面的灯
private Lamp(String opposite,String next,boolean lighted)
{
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}
//判断等是否亮(绿灯为亮,红灯为关闭)
public boolean isLighted()
{
return lighted;
}
//点亮一盏灯,同时点亮和它同组的灯,就是对面的灯
public void light()
{
this.lighted = true;
System.out.println(this.name()+"的绿灯已点亮");
if( this.opposite != null) //因为只有第一行的元素有对面的值,所以必须判断,否则死循环(无限递归了)
{
Lamp.valueOf(this.opposite).light();
}
}
//关灭一盏灯,同时打开他的下一盏灯,并且返回被打开的这盏灯
public Lamp close()
{
this.lighted = false;
Lamp nextLamp = null;
if(this.next != null)
{
nextLamp = Lamp.valueOf(this.next);
nextLamp.light();
}
return nextLamp;
}
}
<p>import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;</p><p>//先打开一盏灯,然后过10秒后关闭这盏灯,然后再过10秒在打开上一次关闭的灯时的返回的那盏灯
public class LampController {
private Lamp curentLamp ;
public LampController()
{
this.curentLamp = Lamp.S2N;
curentLamp.light();
//定义一个定时器线程池,只有1条线程
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
//使用定时器的一个能够延时n秒后以固定周期执行线程的方法, 需要传入命令,就是一个线程的run方法
timer.scheduleAtFixedRate
(new Runnable() {
@Override//关闭当前打开的灯,然后获得被点亮的灯
public void run() {
curentLamp = curentLamp.close();
}
},
10,//initialDelay
10, //period
TimeUnit.SECONDS);// 单位
}
</p><p>}
</p>
<p>import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.Random;</p><p>import javax.swing.text.StyledEditorKit.ForegroundAction;</p><p>/*可以理解为路拥有汽车,因为有多少车这要问路,路上的车辆数这是路的属性
* 所以这个类拥有产生汽车和减少汽车的方法(汽车通过路口后就消失)
* 每一条路都是一个线程,总共有8条路(忽略那四个方向)
* 每条路线上随机增加新的车辆,增加到一个集合中保存。
* 每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本
* 路线保存车的集合中的第一辆车移除,即表示车穿过了路口。
*/
public class Road {</p><p> private String name;
private List <String> vechicles = new ArrayList<String>();
public Road(String name) {
this.name = name ;
//在1-10秒内随机产生一辆车,并加入到车的集合中
//创建一个含有一条线程的线程池
ExecutorService pool = Executors.newSingleThreadExecutor();
//为线程池添加指令然后线程开始执行
pool.execute(new Runnable(){
@Override
public void run()
{
for (int i = 1; i < 1000; i++) {
try {
Thread.sleep(new Random().nextInt(10)*1000);
} catch (Exception e) {
e.printStackTrace();
}
vechicles.add(Road.this.name+"_"+i);
}
}
});
//每隔一秒检查对应的灯是否为绿,是则放行一辆车
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
if(vechicles.size() > 0)
{
if(Lamp.valueOf(Road.this.name).isLighted())//判断是否为绿灯
{
System.out.println(vechicles.remove(0)+"通过路口");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
</p>
<p> </p><p>public class Main {
public static void main (String [] arr)
{
// 创建8条线路线程,开始的时候路灯默认全灭,所以不会有灯通过,车辆是在不断增加的,除非大于1000
String[] strings = {"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N"};
for(String string : strings)
{
new Road(string);
}
//然后,利用LampController让绿灯轮流点亮
new LampController();
}</p><p>}</p>