# Straßenkreuzung - Ampeln mit Threads koordinieren



## R0flC0pterpiL0t (4. Jan 2015)

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

```
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

```
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

```
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

```
/*
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

```
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

```
/*
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;
  }
}
```



```

```


----------



## Gucky (5. Jan 2015)

Momentan laufen die Ampeln alle als Threads und du hast noch einen "Oberthread" pro Kreuzung. Du möchtest aber, dass die Ampelthreads die ganze Zeit laufen. Was müssen Ampeln denn können? Sie müssen von rot auf grün wechseln können, sie müssen von grün auf rot wechseln können, sie müssen gelb blinken können und sie müssen aus sein können.

Ich halte es für besser, wenn du in den Ampeln einen "EventQueue" implementierst. In diesen werden Events vom Oberthread geschrieben. In diesen Events steht die Aufgabe, die erledigt werden soll und eine Zeit, zu der sie gestartet werden soll. Zudem erstellst du noch eine Variable eventSofort, falls irgendetwas sofort geschehen soll.
Die Threads gucken ständig in eventSofort, ob etwas darin steht. Ansonsten gucken sie ständig nach, ob irgendetwas in den Queue geschrieben wurde oder ob die erste Zeit erreicht wurde. Ist dem so, so wird diese Aktion durchgeführt aber es wird trotzdem unablässig in eventSofort nachgeguckt.


Ferner gibt es einen Thread ampelnetz, der alles überwacht und z. B. grüne Wellen schalten kann. Ansonsten lässt er die Kreuzungen machen, was sie für richtig halten. Diese Threads kommunizieren mit Events miteinander.
Ampelnetz schickt die Events an Quadranten, die wiederum in Quadranten aufgeteilt sind und so weiter. Das kannst du beliebig fein machen. Diese Quadranten geben die Events immer an den richtigen Quadranten/an dke richtige Kreuzung weiter.



Das war jetzt leider ein bisschen durcheinander, was daran liegt, dass ich mit dem Handy online bin. Einen Text damit zu schreiben ist kein Hochgenuss. 
Wenn du mich verständlicherweise nicht verstanden hast, kann ich dir wenn es wieder hell ist alles noch mal in epischer Breite erklären


----------



## R0flC0pterpiL0t (5. Jan 2015)

Erstmal danke für deine schnelle Antwort! 

Also eigentlich wollte ich erstmal nur eine Straßenkreuzung haben, auf der Autos fahren können und die Ampeln richtig geschaltet werden, also würde mich erstmal nur das mit dem "EventQueue" interessieren. Aber das andere hört sich bereits sehr interessant an ! 

Zu dem EQ: So wie ich das verstehe, ist das eine detaillierte bzw. präzisere Angabe, die der Oberthread (Supervisor) bei mir den Ampeln gibt. Die AmpelThread-Klasse sagt bereits der AmpelKlasse, welchen Status sie hat durch ein boolean[] (boolean[0] für Rot, boolean[1] für Gelb usw.). Also so in etwa wie diese "Events" die du meinst. Diese Aufgabe wird dann einmal abgearbeitet (zeige Rotgelb an), bis dann eine neue Aufgabe kommt (zeige jetzt Grün an). Die Zeit dazwischen, also in der die Ampel Rotgelb ist, ist halt durch Thread.sleep() bestimmt.

Aber fürs Erste dachte ich würde es reichen, wenn ich hinbekomme, den Ampeln zu sagen, welche rot sein sollen, und welche gerade von Rot auf Rotgelb, dann auf Grün, dann wieder auf Gelbgrün, und zurück auf Rot springen sollen.

Dachte am einfachsten wäre es, dann einfach die jeweiligen Threads pausieren zu lassen, während die anderen beiden Threads eben laufen, und so die zwei Ampeln laufen, und dann abgewechselt wird. Oder was meinst du ?


----------



## Gucky (5. Jan 2015)

Ich denke, es ist besser sie laufen zu lassen. Mit yield() kannst du die CPU Belastung kleiner halten, als mit einer Endlosschleife.

Wenn du sie aber pausieren lassen willst, ginge das aich mit sleep(int).


Mal eine Frage: Du bist ein Chef und möchtest einen Kaffee haben. Du schickst einen Untergebenen los. Sagst du ihm dann "Stelle die Tasse in die Maschine." "Drück auf die Taste mit der dampfenden Tasse." "Warte, bis die Maschine fertig ist." etc. oder sagst du ihm "Ich hätte gerne einen Kaffee ohne Milch mit zwei Würfeln Zucker."?


----------



## R0flC0pterpiL0t (6. Jan 2015)

Gucky hat gesagt.:


> Ich denke, es ist besser sie laufen zu lassen. Mit yield() kannst du die CPU Belastung kleiner halten, als mit einer Endlosschleife.
> 
> Wenn du sie aber pausieren lassen willst, ginge das aich mit sleep(int).



Das wäre dann aber nichts anderes, als mein erster Ansatz, der ja auch funktioniert hat... mit sleep(int x) würden die Ampeln ja immer nur eine festgelegte Zeit x pausieren, unabhängig davon was die anderen Ampeln anzeigen. Kann ja sein, dass ich später die Ampeln auf etwas reagieren lassen möchte, zB. auf die Anzahl der Autos, die warten. So wird dann die Ampeln, an der die meisten Autos warten, auf grün geschaltet. Das andere Ampelpaar muss dann logischerweiße rot anzeigen. Aber wenn die einfach nur von Rot auf Grün wechseln nach einer bereits festgelegten Zeit dann kann ich das ja nicht mehr ? 

Ich würde einfach nur gerne immer wieder den Ampeln sagen können, was sie als nächstes zu tun haben, und zwar nachdem ich die Situation analysiert habe (Sicherheitsaspekt)



> Mal eine Frage: Du bist ein Chef und möchtest einen Kaffee haben. Du schickst einen Untergebenen los. Sagst du ihm dann "Stelle die Tasse in die Maschine." "Drück auf die Taste mit der dampfenden Tasse." "Warte, bis die Maschine fertig ist." etc. oder sagst du ihm "Ich hätte gerne einen Kaffee ohne Milch mit zwei Würfeln Zucker."?



Natürlich letzteres ... ich denke du beziehst dich damit auf folgende Aussage:



> Also so in etwa wie diese "Events" die du meinst. Diese Aufgabe wird dann einmal abgearbeitet (zeige Rotgelb an), bis dann eine neue Aufgabe kommt (zeige jetzt Grün an). Die Zeit dazwischen, also in der die Ampel Rotgelb ist, ist halt durch Thread.sleep() bestimmt.



Die Aussage suggeriert zwar, dass ich immer wieder der Ampel sage, was sie als nächstes zu tun hat, aber durch die while-Schleife, in der die Befehle stehen, was sie als nächstes tun wird, nach dem sie eine bestimmte Zeit das Rot/Rotgelb etc. angezeigt hat, ist das schon festgeschrieben... außerdem muss man einem Computer doch sowieso alles bis aufs kleinste Detail sagen, was er zu tun hat? 

Man kann einem Computer ja nicht sagen "bau mir mal eine funktionierende Straßenkreuzung." analog zu deinem "mach mir einen Kaffee mit zwei Würfeln Zucker und ohne Milch."

Oder lieg ich da jetzt komplett daneben ? Du bist ja eigentlich der mit höherer Kompetenz


----------



## Gucky (6. Jan 2015)

Ich hoffe, ich kann jetzt auf deine beiden Fragen gleichzeitig antworten:
Ich stelle mir das so vor, dass Kreuzung der Ampel nur sagt, was sie anzeigen sollen. Zum Beispiel "Werde Grün". Ob die Ampel gerade noch gelb geblinkt hat, rot war oder schon grün war ist der Kreuzung egal. Sie will nur, dass die Ampel zum angegebenen Zeitpunkt oder sofort grün wird.



			
				R0flC0pterpiL0t hat gesagt.:
			
		

> Man kann einem Computer ja nicht sagen "bau mir mal eine funktionierende Straßenkreuzung." analog zu deinem "mach mir einen Kaffee mit zwei Würfeln Zucker und ohne Milch."


Das Beispiel bezog sich auf die Beziehung zwischen Kreuzung und Ampel. 
Entschuldigung, wenn ich mich da mehrdeutig ausgedrückt habe.

Die Befehle, wie zum Beispiel "Werde grün zu Zeitpunkt 1420557609000" (entspricht "Mach mir einen Kaffee mit zwei Würfeln Zucker und ohne Milch") werden mit einem Event an die Ampeln weitergeleitet. Das Event hat nur zwei Attribute: Die Zeit (ein Zeitpunkt nach Unixzeit oder 0 für sofort) und ein Enum für die Aktion.
Die Variable aktionSofort kann weggelassen werden, da sie alles nur verkompliziert.
Der Kreuzung ist es vollkommen egal, wie die Ampel es bewerkstelligt z. B. gelb zu blinken. Ob mit LEDs, Glühbirnen oder Leuchtkäfern. Hauptsache sie tut es. Und so ist es auch in der Programmierung. Du sagst der Ampel, was sie wann zu tun hat und die Ampel bedient dann den Rechner bzw. die Kaffeemaschine.



Das mit der Kompetenz hast du gesagt aber danke


----------

