java 多線程交通信號(hào)燈模擬過程詳解
這學(xué)期我們java課程的課程設(shè)計(jì)項(xiàng)目----交通信號(hào)燈的線程設(shè)計(jì)
- 實(shí)驗(yàn)?zāi)康模憾嗑€程設(shè)計(jì),同步機(jī)制
- 題意 設(shè)計(jì)一個(gè)交通信號(hào)燈類:
- 變量:位置、顏色(紅、黃、綠)、顯示時(shí)間(秒)。
- 方法:切換信號(hào)燈。
- 創(chuàng)建并啟動(dòng)兩個(gè)線程(東西向、南北向)同時(shí)運(yùn)行。
- 實(shí)驗(yàn)要求
- 設(shè)計(jì)線程。
- 設(shè)計(jì)路口信號(hào)燈示意圖界面。
- 進(jìn)一步將每個(gè)方向的信號(hào)燈分成3種車道燈:左轉(zhuǎn)、直行和右轉(zhuǎn)。
- 根據(jù)車流量進(jìn)行時(shí)間的模糊控制。
在課程設(shè)計(jì)的開始并沒有仔細(xì)看老師的要求,只知道是交通信號(hào)燈。然后就開始各種找資料,百度,網(wǎng)上大量的關(guān)于紅綠燈的設(shè)計(jì)都是參考張孝祥老師的教程,大概的設(shè)計(jì)方法是創(chuàng)建了三個(gè)類 lamp、road、lampcontrol。
然鵝......對(duì).....然鵝又來了,在查了大概兩天資料后,我又反過來看了一遍老師發(fā)的設(shè)計(jì)要求.....這這這.....,光控制燈就行了啊,不要車的啊,捂臉...
所以設(shè)計(jì)思路馬上就變得清晰,根據(jù)張老師的做法,每個(gè)路口都有三個(gè)燈,分別為左轉(zhuǎn)、直行、右轉(zhuǎn),所以一共有12盞燈。按照要求,右轉(zhuǎn)燈為常亮燈,左轉(zhuǎn)和直行燈才有紅綠交替。在除去右轉(zhuǎn)燈的八個(gè)燈里面,又可以分為四組可以兩兩匹配的燈,分別為東西左轉(zhuǎn)南北(平行轉(zhuǎn)垂直)、南北直行(垂直通行)、南北左轉(zhuǎn)東西(垂直轉(zhuǎn)平行)、東西直行(平行通行)。
于是我給這個(gè)12個(gè)燈編了個(gè)號(hào):
emmm 大概就是這樣,但是跟生活中的紅綠燈不同,生活中的都是看對(duì)面路口的燈,我們這里是模擬嘛....就各個(gè)路口用各個(gè)路口的燈唄.....
大致解釋一下,
1號(hào)燈為由南向西的左轉(zhuǎn)燈,2號(hào)燈為由南向北的直行燈,3號(hào)燈為由南向東的右轉(zhuǎn)燈。
4號(hào)燈為由東向北的右轉(zhuǎn)燈,5號(hào)燈為由東向西的直行燈,6號(hào)燈為由東向南的左轉(zhuǎn)燈。
7號(hào)燈為由北向西的右轉(zhuǎn)燈,8號(hào)燈為由北向南的直行燈,9號(hào)燈為由北向東的左轉(zhuǎn)燈。
10號(hào)燈為由西向北的左轉(zhuǎn)燈,11號(hào)燈為由西向東的直行燈,12號(hào)燈為由西向南的右轉(zhuǎn)燈。
然后根據(jù)匹配的原則,大概就是這么一張圖:
我們就可以得到:
這四組信號(hào)燈。
到這里我們思路就很清晰了,我們可以分別為每一組信號(hào)燈開一個(gè)進(jìn)程,然后使四個(gè)進(jìn)程循環(huán)交替進(jìn)行就實(shí)現(xiàn)了綠燈的轉(zhuǎn)換。使用了程的同步技術(shù)。
當(dāng)然,我們都已經(jīng)開了四個(gè)進(jìn)程了,為了錦上添花,我當(dāng)然不介意再加個(gè)小車了hhhhhh
實(shí)驗(yàn)結(jié)果圖:
源代碼:
light類:
package traffic; public class light { int x,y; //燈在畫布上的位置 boolean status; //燈的狀態(tài) public light(int x,int y,boolean islight) { this.x=x; this.y=y; this.status=islight; } public void setlight(boolean sta) { //對(duì)外接口更改燈的狀態(tài) this.status=sta; } }
lamp類:
package traffic; public class lamp implements Runnable { light opposite, now; //相互匹配的兩個(gè)燈 int greentime; //綠燈亮的時(shí)間 int name; //編組 boolean status; //狀態(tài) 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實(shí)現(xiàn)進(jìn)程間的互斥 if (name == mainclass.panel.islight) { //使用輔助變量實(shí)現(xiàn)進(jìn)程按順序循環(huán) //System.out.println("now is: "+name); change(); mainclass.panel.repaint(); try { Thread.sleep(greentime); } catch (InterruptedException e) { e.printStackTrace(); } lock.notifyAll(); //喚醒其他進(jìn)程 change(); mainclass.panel.LampChange(); mainclass.panel.repaint(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { try { lock.wait(); //掛起進(jìn)程 } 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; //十二個(gè)燈 lamp lamp1,lamp2,lamp3,lamp4; //四組信號(hào)燈 static int islight; //實(shí)現(xiàn)進(jìn)程循環(huán)的輔助變量 Random r=new Random(); static public ArrayList<light> lightlist= new ArrayList<light>(); //使用list方便遍歷每個(gè)燈 static public ArrayList<car> carlist= new ArrayList<car>(); //方便遍歷每個(gè)車 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); //創(chuàng)建并啟動(dòng)線程 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); //畫信號(hào)燈板 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<carlist.size();i++) { //畫車 buf=carlist.get(i); g.setColor(Color.BLUE); g.fillRect(buf.x, buf.y, 50, 50); } for(int i=0;i<lightlist.size();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 { //設(shè)置界面 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("南北左轉(zhuǎn)東西:"); lab2=new JLabel("東西直行:"); lab3=new JLabel("東西左轉(zhuǎn)南北:"); 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, "請(qǐng)輸入完整數(shù)據(jù)!", "錯(cuò)誤", 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("設(shè)置"); jmi1=new JMenuItem("開始模擬"); jmi1.addActionListener(this); jmi2=new JMenuItem("退出模擬"); jmi2.addActionListener(this); jmi3=new JMenuItem("隨機(jī)生成小車"); jmi3.addActionListener(this); jmi4=new JMenuItem("更改綠燈時(shí)間"); 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, "請(qǐng)開始模擬再生成小車", "錯(cuò)誤", JOptionPane.INFORMATION_MESSAGE); else panel.addcar(); }else if (e.getSource() == jmi4) { if(mainclass.panel==null) JOptionPane.showMessageDialog(this, "請(qǐng)開始模擬再進(jìn)行設(shè)置", "錯(cuò)誤", JOptionPane.INFORMATION_MESSAGE); else new set(); } } public static void main(String[] args) { new mainclass(); } }
多線程正確性測(cè)試:
我們?cè)趌amp類的run()方法中添加了一句控制臺(tái)打印命令,每次進(jìn)程運(yùn)行時(shí)即會(huì)打印此進(jìn)程的name成員
正確的打印結(jié)果應(yīng)該為 0-1-2-3-4-0-1-2-3-4-.......-1-2-3-....
控制臺(tái)的輸出結(jié)果為:
符合預(yù)測(cè)結(jié)果,實(shí)驗(yàn)完成!
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
阿里云部署SpringBoot項(xiàng)目啟動(dòng)后被殺進(jìn)程的問題解析
這篇文章主要介紹了阿里云部署SpringBoot項(xiàng)目啟動(dòng)后被殺進(jìn)程的問題,本文給大家分享問題原因所在及解決步驟,需要的朋友可以參考下2023-09-09判斷以逗號(hào)分隔的字符串中是否包含某個(gè)數(shù)的實(shí)例
下面小編就為大家?guī)硪黄袛嘁远禾?hào)分隔的字符串中是否包含某個(gè)數(shù)的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11JAVA 并發(fā)容器的一些易出錯(cuò)點(diǎn)你知道嗎
今天給大家?guī)淼奈恼率荍ava并發(fā)編程的相關(guān)知識(shí),文中對(duì)java同步容器與并發(fā)容器做了非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-09-09Java實(shí)現(xiàn)post請(qǐng)求詳細(xì)代碼(帶有參數(shù))
這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)帶有參數(shù)post請(qǐng)求的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-08-08Java HashMap實(shí)現(xiàn)原理分析(一)
這篇文章主要介紹了Java HashMap實(shí)現(xiàn)原理的分析,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-08-08Java(基于Struts2) 分頁實(shí)現(xiàn)代碼
這篇文章介紹了Java(基于Struts2) 分頁實(shí)現(xiàn)代碼,有需要的朋友可以參考一下2013-10-10詳解Java利用同步塊synchronized()保證并發(fā)安全
這篇文章主要介紹了Java利用同步塊synchronized()保證并發(fā)安全,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03