Hallo,
nachdem ich bereits mehrere Versuche unternommen habe, mein Problem zu lösen, und auch bereits nach jemanden, der eine Lösung auf ein vergleichbares Problem gesucht habe, dachte ich mir, ich erstelle schließlich hier bei euch einen Thread, auch weil mir hier bereits einige Male geholfen wurde
Also:
Es geht um eine Straßenkreuzung, die erstmal nur vier Ampeln hat. Jeweils die zwei gegenüberliegenden sollen (logischerweise) synchron laufen. Während also die zwei grün haben, sollen die anderen (auch logischerweise) rot haben, damit es später, wenn ich Autos implementiere, es zu keinen "Unfällen" kommt.
Habe dies zuerst so realisiert, dass ich das eine Ampelpaar um die Zeit, die allgemein eine Ampel benötigt, um einmal von Rot wieder auf Rot zu kommen (alle Phasen durchschreiten), warten lasse. Wenn die Ampel, die zuerst ohne Verzögerung gestartet wurde, wieder Rot ist, wartet diese um die gleiche festgelegte Zeit, bis die andere Ampel eben wieder auf Rot ist usw.
Dies erschien mir jedoch relativ unflexibel und auch ziemlich einfältig. Ist ja nur sturres Code abarbeiten. Keine Ahnung ob Ampeln das in echt auch machen, aber ich wollte jedenfalls meine Ampeln beibringen, aufeinander zu warten mit richtigem Abfragen, ob die andere schon fertig ist, und nicht nur eine festgelegte Zeit zu schlafen, komme was wolle, bis der Zyklus erneut gestartet wird.
Deshalb habe ich versucht, die vier Threads (Ampeln) so zu koordinieren, dass Thread A und B laufen, und die anderen zwei Threads C und D warten, bis A und B einen gewissen Punkt erreicht haben. Dann wartet A und B, bis C und D einen gewissen Punkt erreicht haben. (eben von Rot-Grün-Rot)
Jetzt stellt sich mir aber die Frage... wie lässt man Threads warten?
Habe es bereits mit wait() und notify(), mit interrupt() (Ergebnis: Thread "stirbt" und ist nicht mehr startbar) und mit suspend(), resume(), was jedoch von Java als veraltet angesehen wird, versucht...
Wäre froh darüber, wenn mir jemand einen Tipp geben könnte, wie man das umsetzen kann.
Die Klasse, die am Wichtigsten ist, ist die Straßenkreuzung_Supervisor_Thread.class, sozusagen ein Aufseher, der für den sicheren Ablauf in der Kreuzung verantwortlich ist, und so auch alles steuert. Dort würde ich gerne die Ampeln warten, und starten lassen.
StraßenkreuzungDemo.java
Straßenkreuzung_Background.java
Straßenkreuzung_Ampel.java
Straßenkreuzung_AmpelThread.java
Straßenkreuzung_Supervisor.java
Straßenkreuzung_SupervisorThread.java
nachdem ich bereits mehrere Versuche unternommen habe, mein Problem zu lösen, und auch bereits nach jemanden, der eine Lösung auf ein vergleichbares Problem gesucht habe, dachte ich mir, ich erstelle schließlich hier bei euch einen Thread, auch weil mir hier bereits einige Male geholfen wurde
Also:
Es geht um eine Straßenkreuzung, die erstmal nur vier Ampeln hat. Jeweils die zwei gegenüberliegenden sollen (logischerweise) synchron laufen. Während also die zwei grün haben, sollen die anderen (auch logischerweise) rot haben, damit es später, wenn ich Autos implementiere, es zu keinen "Unfällen" kommt.
Habe dies zuerst so realisiert, dass ich das eine Ampelpaar um die Zeit, die allgemein eine Ampel benötigt, um einmal von Rot wieder auf Rot zu kommen (alle Phasen durchschreiten), warten lasse. Wenn die Ampel, die zuerst ohne Verzögerung gestartet wurde, wieder Rot ist, wartet diese um die gleiche festgelegte Zeit, bis die andere Ampel eben wieder auf Rot ist usw.
Dies erschien mir jedoch relativ unflexibel und auch ziemlich einfältig. Ist ja nur sturres Code abarbeiten. Keine Ahnung ob Ampeln das in echt auch machen, aber ich wollte jedenfalls meine Ampeln beibringen, aufeinander zu warten mit richtigem Abfragen, ob die andere schon fertig ist, und nicht nur eine festgelegte Zeit zu schlafen, komme was wolle, bis der Zyklus erneut gestartet wird.
Deshalb habe ich versucht, die vier Threads (Ampeln) so zu koordinieren, dass Thread A und B laufen, und die anderen zwei Threads C und D warten, bis A und B einen gewissen Punkt erreicht haben. Dann wartet A und B, bis C und D einen gewissen Punkt erreicht haben. (eben von Rot-Grün-Rot)
Jetzt stellt sich mir aber die Frage... wie lässt man Threads warten?
Habe es bereits mit wait() und notify(), mit interrupt() (Ergebnis: Thread "stirbt" und ist nicht mehr startbar) und mit suspend(), resume(), was jedoch von Java als veraltet angesehen wird, versucht...
Wäre froh darüber, wenn mir jemand einen Tipp geben könnte, wie man das umsetzen kann.
Die Klasse, die am Wichtigsten ist, ist die Straßenkreuzung_Supervisor_Thread.class, sozusagen ein Aufseher, der für den sicheren Ablauf in der Kreuzung verantwortlich ist, und so auch alles steuert. Dort würde ich gerne die Ampeln warten, und starten lassen.
StraßenkreuzungDemo.java
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/*
Klasse, die die Straßenkreuzung zeichnet
*/
public class StraßenkreuzungDemo extends JFrame
{
Straßenkreuzung_Background b = new Straßenkreuzung_Background();
Straßenkreuzung_Ampel[] straßenampel_v = new Straßenkreuzung_Ampel[2];
Straßenkreuzung_Ampel[] straßenampel_h = new Straßenkreuzung_Ampel[2];
Straßenkreuzung_AmpelThread[] straßenampel_thread_v = new Straßenkreuzung_AmpelThread[2];
Straßenkreuzung_AmpelThread[] straßenampel_thread_h = new Straßenkreuzung_AmpelThread[2];
Straßenkreuzung_Supervisor superv = new Straßenkreuzung_Supervisor();
Straßenkreuzung_Supervisor_Thread superv_thread = new Straßenkreuzung_Supervisor_Thread(superv);
public static void main(String[] a)
{
StraßenkreuzungDemo frame = new StraßenkreuzungDemo("Straßenkreuzung");
frame.setVisible(true);
}
StraßenkreuzungDemo(String title)
{
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0,0,1000,1000);
setLayout(null);
setResizable(false);
//Hinzufügen der Ampeln
straßenampel_v[0] = new Straßenkreuzung_Ampel(true,false,false,0,"v");
straßenampel_v[0].setBounds(361,360,40,117);
straßenampel_v[0].setBackground(Color.WHITE);
straßenampel_v[1] = new Straßenkreuzung_Ampel(true,false,false,3,"v");
straßenampel_v[1].setBounds(595,517,40,117);
straßenampel_v[1].setBackground(Color.WHITE);
straßenampel_h[0] = new Straßenkreuzung_Ampel(true,false,false,1,"h");
straßenampel_h[0].setBounds(519,363,117,37);
straßenampel_h[0].setBackground(Color.WHITE);
straßenampel_h[1] = new Straßenkreuzung_Ampel(true,false,false,2,"h");
straßenampel_h[1].setBounds(359,593,117,40);
straßenampel_h[1].setBackground(Color.WHITE);
add(straßenampel_v[0]);
add(straßenampel_v[1]);
add(straßenampel_h[0]);
add(straßenampel_h[1]);
straßenampel_thread_v[0] = new Straßenkreuzung_AmpelThread(straßenampel_v[0]);
straßenampel_thread_v[1] = new Straßenkreuzung_AmpelThread(straßenampel_v[1]);
straßenampel_thread_h[0] = new Straßenkreuzung_AmpelThread(straßenampel_h[0]);
straßenampel_thread_h[1] = new Straßenkreuzung_AmpelThread(straßenampel_h[1]);
straßenampel_v[0].setDelay(2);
straßenampel_v[1].setDelay(2);
straßenampel_h[0].setDelay(2);
straßenampel_h[1].setDelay(2);
/*straßenampel_thread_v[0].start();
straßenampel_thread_v[1].start();
straßenampel_thread_h[0].start();
straßenampel_thread_h[1].start();*/
superv.add(straßenampel_v[0],straßenampel_thread_v[0]);
superv.add(straßenampel_h[0],straßenampel_thread_h[0]);
superv.add(straßenampel_v[1],straßenampel_thread_v[1]);
superv.add(straßenampel_h[1],straßenampel_thread_h[1]);
superv_thread.start();
b.setBounds(0,0,1000,1000);
add(b);
}
}
Straßenkreuzung_Background.java
Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import javax.imageio.*;
/*
Klasse, die den Hintergrund liefert
*/
public class Straßenkreuzung_Background extends JPanel
{
BufferedImage img;
Straßenkreuzung_Background()
{
try
{
img = ImageIO.read(new File("straßenkreuzung_1000x1000.png"));
}
catch (IOException e)
{
}
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(img,0,0,null);
}
}
Straßenkreuzung_Ampel.java
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/*
Klasse, die die Ampeln neu zeichnet
*/
public class Straßenkreuzung_Ampel extends JPanel
{
boolean[] status = new boolean[3];
public int delay = 1;
int id;
int[] gre = new int[2];
int[] yel = new int[2];
int[] red = new int[2];
String lage;
boolean rotphase;
public Straßenkreuzung_Ampel(boolean red, boolean yel, boolean gre, int identify, String lage)
{
this.status[0] = red;
this.status[1] = yel;
this.status[2] = gre;
this.id = identify;
this.lage = lage;
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
switch (id)
{
case 0 :
gre[0] = 7;
gre[1] = 0;
yel[0] = 7;
yel[1] = 40;
red[0] = 7;
red[1] = 80;
break;
case 1 :
gre[0] = 80;
gre[1] = 0;
yel[0] = 40;
yel[1] = 0;
red[0] = 7;
red[1] = 0;
break;
case 2 :
gre[0] = 7;
gre[1] = 0;
yel[0] = 40;
yel[1] = 0;
red[0] = 80;
red[1] = 0;
break;
case 3 :
gre[0] = 7;
gre[1] = 80;
yel[0] = 7;
yel[1] = 40;
red[0] = 7;
red[1] = 0;
break;
default:
} // end of switch
if (lage.equals("v"))
{
if (status[0] && !status[1])
{
g.setColor(Color.RED);
g.fillOval(red[0],red[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(red[0],red[1],30,30);
g.drawOval(red[0]+1,red[1]+1,29,29);
} // end of if
else
{
if (status[0] && status[1])
{
g.setColor(Color.RED);
g.fillOval(red[0],red[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(red[0],red[1],30,30);
g.drawOval(red[0]+1,red[1]+1,29,29);
g.setColor(Color.YELLOW);
g.fillOval(yel[0],yel[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(yel[0],yel[1],30,30);
g.drawOval(yel[0]+1,yel[1]+1,30,30);
} // end of if
else
{
if (status[2] && !status[1])
{
g.setColor(Color.GREEN);
g.fillOval(gre[0],gre[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(gre[0],gre[1],30,30);
g.drawOval(gre[0]+1,gre[1]+1,29,29);
} // end of if
else
{
if (status[1] && status[2])
{
g.setColor(Color.YELLOW);
g.fillOval(yel[0],yel[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(yel[0],yel[1],30,30);
g.drawOval(yel[0]+1,yel[1]+1,30,30);
g.setColor(Color.GREEN);
g.fillOval(gre[0],gre[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(gre[0],gre[1],30,30);
g.drawOval(gre[0]+1,gre[1]+1,29,29);;
} // end of if
} // end of if-else
} // end of if-else
} // end of if-else
} // end of if
else
{
if (status[0] && !status[1])
{
g.setColor(Color.RED);
g.fillOval(red[0],red[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(red[0],red[1],30,30);
g.drawOval(red[0]+1,red[1]+1,29,29);
} // end of if
else
{
if (status[0] && status[1])
{
g.setColor(Color.RED);
g.fillOval(red[0],red[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(red[0],red[1],30,30);
g.drawOval(red[0]+1,red[1]+1,29,29);
g.setColor(Color.YELLOW);
g.fillOval(yel[0],yel[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(yel[0],yel[1],30,30);
g.drawOval(yel[0]+1,yel[1]+1,30,30);
} // end of if
else
{
if (status[2] && !status[1])
{
g.setColor(Color.GREEN);
g.fillOval(gre[0],gre[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(gre[0],gre[1],30,30);
g.drawOval(gre[0]+1,gre[1]+1,29,29);
} // end of if
else
{
if (status[1] && status[2])
{
g.setColor(Color.YELLOW);
g.fillOval(yel[0],yel[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(yel[0],yel[1],30,30);
g.drawOval(yel[0]+1,yel[1]+1,30,30);
g.setColor(Color.GREEN);
g.fillOval(gre[0],gre[1],30,30);
g.setColor(Color.BLACK);
g.drawOval(gre[0],gre[1],30,30);
g.drawOval(gre[0]+1,gre[1]+1,29,29);;
} // end of if
} // end of if-else
} // end of if-else
} // end of if-else
} // end of if-else
}
public void setStatus(boolean[] b)
{
this.status = b;
}
public boolean[] getStatus()
{
return status;
}
public void setDelay(int delay)
{
this.delay = delay;
}
public int getDelay()
{
return delay;
}
public void setLage(String lage)
{
this.lage = lage;
}
public String getLage()
{
return lage;
}
}
Straßenkreuzung_AmpelThread.java
Java:
/*
Klasse, die für den zeitlichen Ablauf zuständig ist
*/
public class Straßenkreuzung_AmpelThread extends Thread
{
public boolean[] status = new boolean[3];
public Straßenkreuzung_Ampel ampel;
boolean suspended = false;
int countdraw=0;
public Straßenkreuzung_AmpelThread(Straßenkreuzung_Ampel ampel)
{
this.ampel = ampel;
}
public void run()
{
while (true)
{
System.out.println("Thread-"+ampel.id + " is running!");
while (true)
{
status = ampel.getStatus();
switch (checkStatus())
{
//Rotphase?
case 1 :
//Rotgelbphase
try
{
sleep(1000*ampel.getDelay());
}
catch(Exception e)
{
}
status[1] = true;
ampel.setStatus(status);
ampel.repaint();
countdraw++;
break;
//Rotgelbphase ?
case 2 :
//Grünphase
try
{
sleep(500);
}
catch(Exception e)
{
}
status[0] = false;
status[1] = false;
status[2] = true;
ampel.setStatus(status);
ampel.repaint();
countdraw++;
break;
//Grünphase?
case 3 :
//Grüngelbphase
try
{
sleep(2000*ampel.getDelay());
}
catch(Exception e)
{
}
status[1] = true;
ampel.setStatus(status);
ampel.repaint();
countdraw++;
break;
//Grüngelbphase?
case 4 :
//Rotphase
try
{
sleep(500);
}
catch(Exception e)
{
}
//Rotphase
status[0] = true;
status[1] = false;
status[2] = false;
ampel.setStatus(status);
ampel.repaint();
countdraw++;
break;
default:
break;
} // end of switch
if (countdraw==4)
{
try
{
sleep(2500*ampel.getDelay()+1000);
}
catch(Exception e)
{
}
countdraw = 0;
} // end of if
} // end of while
} // end of while
}
public int checkStatus()
{
if (status[0] && !status[1])
{
return 1;
} // end of if
else
{
if (status[0] && status[1])
{
return 2;
} // end of if
else
{
if (status[2] && !status[1])
{
return 3;
} // end of if
else
{
return 4;
} // end of if
} // end of if-else
} // end of if-else
}
}
Straßenkreuzung_Supervisor.java
Java:
import java.util.ArrayList;
/*
Klasse, die für einen sicheren Verkehrsablauf verantwortlich ist
*/
public class Straßenkreuzung_Supervisor
{
ArrayList<Straßenkreuzung_Ampel> list = new ArrayList<Straßenkreuzung_Ampel>();
ArrayList<Straßenkreuzung_AmpelThread> threadlist = new ArrayList<Straßenkreuzung_AmpelThread>();
public void add(Straßenkreuzung_Ampel ampel, Straßenkreuzung_AmpelThread ampelThread)
{
list.add(ampel);
String s = list.get(list.size()-1).getLage();
System.out.println(s);
System.out.println(list.get(list.size()-1).getStatus()[0]);
System.out.println(list.get(list.size()-1).getStatus()[1]);
System.out.println(list.get(list.size()-1).getStatus()[2]);
threadlist.add(ampelThread);
}
}
Straßenkreuzung_SupervisorThread.java
Java:
/*
2. Klasse, die für einen sicheren Verkehrsablauf verantwortlich ist
*/
public class Straßenkreuzung_Supervisor_Thread extends Thread
{
public Straßenkreuzung_Supervisor sv = new Straßenkreuzung_Supervisor();
public Straßenkreuzung_Supervisor_Thread(Straßenkreuzung_Supervisor sv)
{
this.sv = sv;
}
public void run()
{
int i,j,x=0;
for (i=0;i<sv.threadlist.size();i++)
{
sv.threadlist.get(i).start();
if (i%2!=0)
{
try
{
sv.threadlist.get(i).suspend();
} catch(Exception e)
{
}
} // end of if
} // end of for
int[][] statusse = new int[4][4];
for (i=0;i<statusse.length;i++)
{
statusse[i][0] = i+1;
} // end of for
int[] converted = new int[3];
while(true)
{
for (i=0;i<sv.list.size();i++)
{
converted = convertInt(sv.list.get(i).getStatus());
for (j=0;j<converted.length;j++)
{
statusse[i][j+1] = converted[j];
} // end of for
} // end of for
for (i=0;i<statusse.length;i++)
{
for (j=0;j<statusse[0].length;j++)
{
System.out.print(statusse[i][j]);
} // end of for
System.out.println();
} // end of for
System.out.println("switch-case : " + checkStatusse(statusse));
switch (checkStatusse(statusse))
{
case 1 :
System.out.println("x: " + x);
if (x!=1 && x!=0)
{
if (x==2)
{
System.out.println("Wechsel von vertikal grün auf horizontal Grün !");
for (i=0;i<sv.threadlist.size();i++)
{
if (sv.threadlist.get(i).isSuspended())
{
sv.threadlist.get(i).resume();
}
else
{
sv.threadlist.get(i).suspend();
} // end of if-else
System.out.println("Thread suspended? : " + sv.threadlist.get(i).isSuspended());
} // end of for
} // end of if
else
{
System.out.println("Wechsel von horizontal grün auf vertikal Grün !");
for (i=0;i<sv.threadlist.size();i++)
{
if (sv.threadlist.get(i).isSuspended())
{
sv.threadlist.get(i).resume();
} // end of if
else
{
try
{
sv.threadlist.get(i).suspend();
} catch(Exception e)
{
}
} // end of if-else
System.out.println("Thread suspended? : " + sv.threadlist.get(i).isSuspended());
} // end of for
} // end of if-else
System.out.println("alle Rot !");
} // end of if
x = 1;
break;
case 2 :
if (x!=2)
{
System.out.println("vertikal grün !");
} // end of if
x = 2;
break;
case 3 :
if (x!=3)
{
System.out.println("horizontal grün !");
} // end of if
x = 3;
break;
default:
System.out.println("Gelbübergang");
} // end of switch*/
} // end of while
}
public int checkStatusse(int[][] statusse)
{
if (checkStatus(statusse[0])==1 && checkStatus(statusse[1])==1)
{
//alle Rot wenn Ampel1 und Ampel2 Rot
return 1;
} // end of if
else
{
if (checkStatus(statusse[0])==3 && checkStatus(statusse[1])==1)
{
//Ampel1 Grün und Ampel2 Rot
return 2;
} // end of if
else
{
if (checkStatus(statusse[0])==1 && checkStatus(statusse[1])==3)
{
//Ampel1 Rot Ampel2 Grün
return 3;
} // end of if
else
{
return 4;
} // end of if-else
} // end of if
} // end of if-else
}
public int checkStatus(int[] status)
{
if (status[1]==1 && status[2]==0)
{
//Rot
return 1;
} // end of if
else
{
if (status[1]==1 && status[2]==1)
{
//Rotgelb
return 2;
} // end of if
else
{
if (status[3]==1 && status[2]==0)
{
//Grün
return 3;
} // end of if
else
{
//Gelbgrün
return 4;
} // end of if
} // end of if-else
} // end of if-else
}
public int[] convertInt(boolean[] s)
{
int i;
int[] a = new int[s.length];
for (i=0;i<s.length;i++)
{
if (s[i])
{
a[i] = 1;
} // end of if
else {
a[i] = 0;
} // end of if-else
} // end of for
return a;
}
}
Java:
Anhänge
Zuletzt bearbeitet: