这学期我们java课程的课程设计项目----交通信号灯的线程设计

实验目的:多线程设计,同步机制

题意 设计一个交通信号灯类:

变量:位置、颜色(红、黄、绿)、显示时间(秒)。

方法:切换信号灯。

创建并启动两个线程(东西向、南北向)同时运行。

实验要求

设计线程。

设计路口信号灯示意图界面。

进一步将每个方向的信号灯分成3种车道灯:左转、直行和右转。

根据车流量进行时间的模糊控制。

在课程设计的开始并没有仔细看老师的要求,只知道是交通信号灯。然后就开始各种找资料,百度,网上大量的关于红绿灯的设计都是参考张孝祥老师的教程,大概的设计方法是创建了三个类 lamp、road、lampcontrol。

然鹅......对.....然鹅又来了,在查了大概两天资料后,我又反过来看了一遍老师发的设计要求.....这这这.....,光控制灯就行了啊,不要车的啊,捂脸...

所以设计思路马上就变得清晰,根据张老师的做法,每个路口都有三个灯,分别为左转、直行、右转,所以一共有12盏灯。按照要求,右转灯为常亮灯,左转和直行灯才有红绿交替。在除去右转灯的八个灯里面,又可以分为四组可以两两匹配的灯,分别为东西左转南北(平行转垂直)、南北直行(垂直通行)、南北左转东西(垂直转平行)、东西直行(平行通行)。

于是我给这个12个灯编了个号:

emmm 大概就是这样,但是跟生活中的红绿灯不同,生活中的都是看对面路口的灯,我们这里是模拟嘛....就各个路口用各个路口的灯呗.....

大致解释一下,

1号灯为由南向西的左转灯,2号灯为由南向北的直行灯,3号灯为由南向东的右转灯。

4号灯为由东向北的右转灯,5号灯为由东向西的直行灯,6号灯为由东向南的左转灯。

7号灯为由北向西的右转灯,8号灯为由北向南的直行灯,9号灯为由北向东的左转灯。

10号灯为由西向北的左转灯,11号灯为由西向东的直行灯,12号灯为由西向南的右转灯。

然后根据匹配的原则,大概就是这么一张图:

我们就可以得到:

这四组信号灯。

到这里我们思路就很清晰了,我们可以分别为每一组信号灯开一个进程,然后使四个进程循环交替进行就实现了绿灯的转换。使用了程的同步技术。

当然,我们都已经开了四个进程了,为了锦上添花,我当然不介意再加个小车了hhhhhh

实验结果图:

源代码:

light类:

package traffic;

public class light {

int x,y; //灯在画布上的位置

boolean status; //灯的状态

public light(int x,int y,boolean islight) {

this.x=x;

this.y=y;

this.status=islight;

}

public void setlight(boolean sta) { //对外接口更改灯的状态

this.status=sta;

}

}

lamp类:

package traffic;

public class lamp implements Runnable {

light opposite, now; //相互匹配的两个灯

int greentime; //绿灯亮的时间

int name; //编组

boolean status; //状态

static Object lock = new Object();

public lamp(light l0, light l2,int gt, boolean st, int name) {

now = l0;

opposite = l2;

status = st;

greentime = gt;

this.name = name;

lightstatues();

}

public void change() {

this.status = !(this.status);

lightstatues();

}

public void setgreentime(int time) {

this.greentime=time;

}

public int getgreentime() {

return this.greentime;

}

public void lightstatues() {

opposite.setlight(status);

now.setlight(status);

}

public void run() {

while (true) {

synchronized (lock) { //使用synchronized实现进程间的互斥

if (name == mainclass.panel.islight) { //使用辅助变量实现进程按顺序循环

//System.out.println("now is: "+name);

change();

mainclass.panel.repaint();

try {

Thread.sleep(greentime);

} catch (InterruptedException e) {

e.printStackTrace();

}

lock.notifyAll(); //唤醒其他进程

change();

mainclass.panel.LampChange();

mainclass.panel.repaint();

try {

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

} else {

try {

lock.wait(); //挂起进程

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

}

Mypanel类:

package traffic;

import java.awt.Color;

import java.awt.Graphics;

import java.util.ArrayList;

import java.util.Random;

import javax.swing.JPanel;

public class Mypanel extends JPanel {

light l0,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12; //十二个灯

lamp lamp1,lamp2,lamp3,lamp4; //四组信号灯

static int islight; //实现进程循环的辅助变量

Random r=new Random();

static public ArrayList lightlist= new ArrayList(); //使用list方便遍历每个灯

static public ArrayList carlist= new ArrayList();          //方便遍历每个车

public Mypanel() {

// TODO Auto-generated constructor stub

l0=addlist(l0, 212, 316, false);

l2=addlist(l2, 242, 316, false);

l3=addlist(l3, 272, 316, true);

l4=addlist(l4, 316, 116, true);

l5=addlist(l5, 316, 146, false);

l6=addlist(l6, 316, 176, false);

l7=addlist(l7,116 , 70, true);

l8=addlist(l8, 146, 70, false);

l9=addlist(l9, 176, 70, false);

l10=addlist(l10, 70, 212, false);

l11=addlist(l11, 70, 242, false);

l12=addlist(l12, 70, 272, true

lamp1=new lamp(l9,l0,2000,false,0);

lamp2=new lamp(l11,l5,2000,false,1);

lamp3=new lamp(l10,l6,2000,false,2);

lamp4=new lamp(l8,l2,2000,false,3);

islight = 0 ;

Thread t1=new Thread(lamp1); //创建并启动线程

Thread t2=new Thread(lamp2);

Thread t3=new Thread(lamp3);

Thread t4=new Thread(lamp4);

t1.start();

t2.start();

t3.start();

t4.start();

}

light addlist(light a,int x,int y,boolean sta) {

a=new light(x,y,sta);

lightlist.add(a);

return a;

}

public void addcar() { //生成小车

int now,next;

now=r.nextInt(4);

next=r.nextInt(4);

car testcar=null;

while(now==next)

next=r.nextInt(4);

switch(now) {

case 0:

testcar=new car(now,next,l0,l2,l3);

break;

case 1:

testcar=new car(now,next,l6,l5,l4);

break;

case 2:

testcar=new car(now,next,l9,l8,l7);

break;

case 3:

testcar=new car(now,next,l10,l11,l12);

break;

}

carlist.add(testcar);

Thread catt=new Thread(testcar);

catt.start();

}

public void LampChange() {

islight=(islight+1)%4;

}

public void paint(Graphics g) {

super.paint(g);

g.setColor(Color.darkGray); //画路

g.fillRect(0, 100, 400, 6);

g.fillRect(0, 300, 400, 6);

g.fillRect(100, 0, 6, 400);

g.fillRect(300, 0, 6, 400);

g.setColor(Color.gray);

g.fillRect(0, 200, 400, 2);

g.fillRect(200, 0, 2, 400);

g.setColor(Color.blue);

g.setColor(Color.black); //画信号灯板

g.fillRect(202,306, 100, 40);

g.fillRect(306,106, 40, 100);

g.fillRect(106,60, 100, 40);

g.fillRect(60,202,40, 100);

light temp;

car buf;

for(int i=0;i

buf=carlist.get(i);

g.setColor(Color.BLUE);

g.fillRect(buf.x, buf.y, 50, 50);

}

for(int i=0;i

temp=lightlist.get(i);

if(temp.status)

g.setColor(Color.green);

else

g.setColor(Color.RED);

g.fillOval(temp.x, temp.y, 20, 20);

}

}

}

welcomepanel类:

package traffic;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import javax.swing.JPanel;

public class welcomepanel extends JPanel implements Runnable{ //开始界面

int info = 0;

Boolean isLive=true;

public void paint(Graphics g) {

super.paint(g);

g.fillRect(0, 0, 420,450);

g.setColor(Color.red);

g.setFont(new Font("微软雅黑", Font.BOLD, 30));

if (info % 2 == 0) {

g.drawString("多线程红绿灯模拟", 80, 150);

}

}

public void run() {

// TODO Auto-generated method stub

while (true) {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

info++;

this.repaint();

if (isLive == false) {

break;

}

}

}

}

set类:

package traffic;

import java.awt.FlowLayout;

import java.awt.GridLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JButton;

import javax.swing.JDialog;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JTextField;

public class set extends JFrame implements ActionListener { //设置界面

JLabel lab1,lab2,lab3,lab4;

JTextField jtext1,jtext2,jtext3,jtext4;

JPanel panel1,panel2,panel3,panel4;

JButton jb1,jb2;

int time1,time2,time3,time4;

public set(){

lab1=new JLabel("南北左转东西:");

lab2=new JLabel("东西直行:");

lab3=new JLabel("东西左转南北:");

lab4=new JLabel("南北直行:");

time1=mainclass.panel.lamp1.getgreentime();

time2=mainclass.panel.lamp2.getgreentime();

time3=mainclass.panel.lamp3.getgreentime();

time4=mainclass.panel.lamp4.getgreentime();

jtext1=new JTextField(String.valueOf(time1));

jtext2=new JTextField(String.valueOf(time2));

jtext3=new JTextField(String.valueOf(time3));

jtext4=new JTextField(String.valueOf(time4));

jb1=new JButton("确定");

jb1.addActionListener(this);

jb2=new JButton("取消");

jb2.addActionListener(this);

this.setLayout(new GridLayout(5,2,10,5));

this.add(lab1);

this.add(jtext1);

this.add(lab2);

this.add(jtext2);

this.add(lab3);

this.add(jtext3);

this.add(lab4);

this.add(jtext4);

this.add(jb1);

this.add(jb2);

this.setLocationRelativeTo(null);

this.setSize(200, 200);

this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

this.setResizable(false);

this.setVisible(true);

}

public void actionPerformed(ActionEvent e) {

if(e.getSource()==jb1) {

if(jtext1.getText().length()==0||jtext2.getText().length()==0||jtext3.getText().length()==0||jtext4.getText().length()==0)

JOptionPane.showMessageDialog(this, "请输入完整数据!", "错误", JOptionPane.INFORMATION_MESSAGE);

else {

mainclass.panel.lamp1.setgreentime(Integer.parseInt(jtext1.getText()));

mainclass.panel.lamp2.setgreentime(Integer.parseInt(jtext2.getText()));

mainclass.panel.lamp3.setgreentime(Integer.parseInt(jtext3.getText()));

mainclass.panel.lamp4.setgreentime(Integer.parseInt(jtext4.getText()));

this.dispose();

}

}else if(e.getSource()==jb2){

this.dispose();

}

}

}

mainclass主类:

package traffic;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JMenuItem;

import javax.swing.JOptionPane;

public class mainclass extends JFrame implements ActionListener{

static Mypanel panel;

JMenuBar jmb;

JMenu jm1, jm2;

JMenuItem jmi1, jmi2,jmi3,jmi4;

welcomepanel sp;

mainclass(){

this.setTitle("traffic lamp");

this.setSize(420,450);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

jmb=new JMenuBar();

jm1=new JMenu("控制");

jm2=new JMenu("设置");

jmi1=new JMenuItem("开始模拟");

jmi1.addActionListener(this);

jmi2=new JMenuItem("退出模拟");

jmi2.addActionListener(this);

jmi3=new JMenuItem("随机生成小车");

jmi3.addActionListener(this);

jmi4=new JMenuItem("更改绿灯时间");

jmi4.addActionListener(this);

jm1.add(jmi1);

jm1.add(jmi2);

jm1.add(jmi3);

jm2.add(jmi4);

jmb.add(jm1);

jmb.add(jm2);

this.setJMenuBar(jmb);

sp=new welcomepanel();

Thread t=new Thread(sp);

t.start();

this.setContentPane(sp);

this.setLocationRelativeTo(null);

this.setResizable(false);

this.setVisible(true);

}

public void actionPerformed(ActionEvent e) {

if(e.getSource()==jmi1) {

sp.isLive=false;

this.remove(sp);

panel = new Mypanel();

this.setContentPane(panel);

this.setVisible(true);

}else if(e.getSource()==jmi2) {

System.exit(0);

}else if(e.getSource()==jmi3) {

if(panel==null)

JOptionPane.showMessageDialog(this, "请开始模拟再生成小车", "错误", JOptionPane.INFORMATION_MESSAGE);

else panel.addcar();

}else if (e.getSource() == jmi4) {

if(mainclass.panel==null)

JOptionPane.showMessageDialog(this, "请开始模拟再进行设置", "错误", JOptionPane.INFORMATION_MESSAGE);

else new set();

}

}

public static void main(String[] args) {

new mainclass();

}

}

多线程正确性测试:

我们在lamp类的run()方法中添加了一句控制台打印命令,每次进程运行时即会打印此进程的name成员

正确的打印结果应该为 0-1-2-3-4-0-1-2-3-4-.......-1-2-3-....

控制台的输出结果为:

符合预测结果,实验完成!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

java模拟交通信号灯_java 多线程交通信号灯模拟过程详解相关推荐

  1. 基于java的动态口令_java动态口令登录实现过程详解

    1.实现一个ItsClient 客户端用来实例化调用验证功能 public class ItsClient { private static final String routing = " ...

  2. Java单机部署,Nacos docker单机模式部署实现过程详解

    Nacos 的部署,我使用的时docker 部署(单机模式 mysql),官网文档:https://nacos.io/zh-cn/docs/quick-start-docker.html 拉取代码: ...

  3. java 接口 返回值_java api返回值的标准化详解

    api返回值的标准化 例如 {"status":200,"message":"操作成功","data":"{\ ...

  4. java 检查bytebuf长度_Java学习笔记16-Netty缓冲区ByteBuf详解

    Java学习笔记16-Netty缓冲区ByteBuf详解 Netty自己的ByteBuf ByteBuf是为解决ByteBuffer的问题和满足网络应用程序开发人员的日常需求而设计的. JDK Byt ...

  5. java语言链栈_Java语言实现数据结构栈代码详解

    近来复习数据结构,自己动手实现了栈.栈是一种限制插入和删除只能在一个位置上的表.最基本的操作是进栈和出栈,因此,又被叫作"先进后出"表. 首先了解下栈的概念: 栈是限定仅在表头进行 ...

  6. java tostring格式化日期_java日期格式化SimpleDateFormat的使用详解

    日期和时间格式由 日期和时间模式字符串 指定.在 日期和时间模式字符串 中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' 被解释为模式字母,用来表示日期或时间字符串元素.文本可以使用单引 ...

  7. java打印菱形图案_java打印出菱形图案实例详解

    第一步:首先对图像进行解析 想要打印该图形必须要进行多层循环嵌套,分两个部分进行打印. 第一部分为上半部分前四行,他们是递增的关系,后半部分后三行为递减关系,由此可以得出我们需要写两个打的循环.并且由 ...

  8. java的匿名函数_JAVA语言中的匿名函数详解

    本文主要向大家介绍了JAVA语言中的匿名函数详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 一.使用匿名内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: ...

  9. java 迭代器的优缺点_java迭代器和for循环优劣详解

    在进行迭代的时候,程序运行的效率也是我们挑选迭代方法的重要原因.目前有三种迭代方法:for循环.迭代器和Foreach.前两者相信大家都非常熟悉,为了更加直观分析效率的不同,我们还加入Foreach一 ...

  10. java random函数用法_JAVA的Random类的用法详解

    Random类主要用来生成随机数,本文详解介绍了Random类的用法,希望能帮到大家. Random类 (java.util) Random类中实现的随机算法是伪随机,也就是有规则的随机.在进行随机时 ...

最新文章

  1. 蓝牙mesh网络技术的亮点
  2. Microsoft Expression Blend 2 密钥,key
  3. 编写自动调试器以在测试执行期间捕获异常
  4. Java中key可以重复的Map集合:IdentityHashMap
  5. inner join 和 exists 效率_19 个让 MySQL 效率提高 3 倍的 SQL 优化技巧
  6. 5.21工作记录(修改页面跳转,去掉多余的js;增加图片清除功能)
  7. 无法打开计算机的组策略,win7系统电脑本地组策略打不开无法运行的解决方法...
  8. 手机游戏中的社交互动与任务剧情
  9. Netflix Media Database - 架构设计和实现
  10. Jenkins 持续集成平台构建之通过git提交代码
  11. RIDE指定log和report的输出目录
  12. JavaScript教程---洪恩在线
  13. T60 Fan Error 解决办法.转自ZOL产品论坛-作者zxymb
  14. 马哥python_马哥Python 开发9期
  15. private的使用
  16. 浅释丹道筑基功―—―混元桩【转载】
  17. [向前一小步]Android简单实现指纹识别登录
  18. MSVC X64 函数中的 RSP, RBP 和 Calling Convention
  19. 架构设计文档模板之1:备选方案模板
  20. 布尔运算 : ^(异或运算XOR)、(与运算AND)、|(或运算OR)、 、~(非门NOT)

热门文章

  1. 虚拟机网络适配器下的3种网络模式(主机模式、桥接模式和NAT模式)
  2. 【写论文用到的几个偷懒的网站和软件】
  3. java 计算某个时间段在多个时间段中分别用时
  4. php面向对象--php面向对象ppt
  5. springboot模板
  6. 程序员趣图:有时候我的代码就是这样子……
  7. NavicatPremium写的MySQL文件去哪?
  8. 说说开源中国社区的愚人节
  9. 请问?外包到腾讯工作是怎样一种体验?
  10. ip (internet protocol)