# Countdownfunktion gesucht



## ehrich45 (8. Aug 2007)

hallo,
ich suche etwas dasn ich als timer nehmen kann.
das ganze sollte so ablaufen. der timer läuft 30 sekunden bis er auf null ist. wenn er auf null ist soll er eine funktion ausführen. wenn er vorher , vor ablauf der 30 sekunden von einer anderen funktion gestartet wird dann fängt der timer wieder von vorne an zu laufen.

wie kann ich so etwas realisieren ??

vielen dank !!
gruß


----------



## The_S (8. Aug 2007)

Stichwort Timer und Thread. Schau dir die Klassen an, such im Forum und schlage Tutorials nach  . Wenn du dann noch ein konkretes Problem/Frage hast, zöger nicht sie hier zu stellen  .


----------



## tuxedo (8. Aug 2007)

Ich hab das, ist schon recht lange her, in meinen Anfangszeiten mit nem Thread gelöst.. Hatte aber das "Problem" dass ich zu einer bestimmten Uhrzeit etwas ausführen wollte. 
Hab dann einfach ausgerechnet wie lange das noch hin ist und hab den Thread erstmal so lange schlafen geschickt, und dann meine Aktion ausgeführt.


----------



## jPat (8. Aug 2007)

```
class myThread exstends Thread{

private int time = 30 // sekunden
private boolean running = false;
public void start(){
   if (time < 30) time = 30;  
   running = true
}

public void run(){

   while (running){
       sleepOneSec();
   }
 dieFunktion();
}

private void sleepOneSec(){
   try
   {
       Thread.sleep(1000);
       time--;
       if (time == 0 ) running = false;
}
catch (Exception e) {}

}

}
```

hab es zwar nicht ausprobiert, aber es sollte so funktionieren ...  :wink:


----------



## ehrich45 (8. Aug 2007)

schonmal vielen dank fuer eure mühen.

ich habe das grad versucht einzubinden.. aber ich glaub ich habe einen denkfehler gemacht.

also mein plan ist dieser:

ich habe in einer datenbank sagen wir 5 datensätze die alle auf true stehen. alle haben 30 sekunden zeit zum laufen. alle 15sek bekommt jeder datensatz das signal noch "da" zu sein. dann soll der timer von vorne beginnen. 
falls dann bei einem datensatz einmal kein signal kommt soll dieser auf false stehen. 
aber alle unabhängig voneinander.


ich hoffe ihr könnt mir weiter helfen.

viele dank !!

gruß


----------



## jPat (8. Aug 2007)

Du kannst vom Thread doch 5 instanzen erzeugen

```
MyThread mtArray[]  = new MyThread[5];

for (int i = 0; i<5; i++){
mtArray[i] = new MyThread(sql[i]); //  in sql sind deine abfragen auf die Datenbank gekapselt
 mtArray[i].start();
}
```
Du kannst in den Konstruktor der Klasse MyThread das Objekt hineingeben, welches die Datenbankaufrufe für dich erledigt. 


```
class MyThread exstends Thread{

private int time = 30 // sekunden
private boolean running = false;
private deineSQLWriterKlasse   sql;/ / oder deine CheckKlasse

MyTread(deineSQLWriterKlasse sql ){
this.sql =  sql;
}

public void start(){
   if (time < 30) time = 30; 
   running = true
}

public void run(){

   while (running){
       sleepOneSec();
       if (time == 15 ){  
          if (sql.bistDuDa()==true) {
          timer=30;
        } else {stelle auf false}
       }
   }
dieFunktion();
}

private void sleepOneSec(){
   try
   {
       Thread.sleep(1000);
       time--;
       if (time == 0 ) running = false;
}
catch (Exception e) {}

}

}
```

PS: bitte mal deinen Code posten ....


----------



## tuxedo (8. Aug 2007)

Ich glaube du hast den Beispielcode nicht verstanden. Genau das macht der nämlich. Naja, fast. Das setzten des "noch da" Flags in der DB musst du in Zeile 16 -> dieFunktion(); machen. Und pro Datensatz einen solchen Thread erzeugen.

Das das Beispiel nicht die allumfassende Komplettlösung deines Problems darstellt ist klar, oder?


----------



## Guest (15. Aug 2007)

hallo, könnt ihr mir bitte nochmal helfen ?? ich komme damit nicht so ganz klar.

also:

```
if(level.equals("<199>")){
		   level = "Machine-Online";
		  System.out.println("Maschine: "+SsenderId+","+Stype+" online");
		  
		  try {
			 
			  CheckOnline mtArray[]  = new CheckOnline[5]; 

			  for (int i = 0; i<Statusdaten.size(); i++){ 
			 // mtArray[i] = new CheckOnline(sql[i]); //  in sql sind deine abfragen auf die Datenbank gekapselt 
			  mtArray[i].start();
			  
			  } 
			SqlData.setMachineOnline(SsenderId);
		} catch (SQLException e) {e.printStackTrace();}
	   }
```

so habe ich das in meine "empfangsklasse" eingebunden. also ich muss nichts prüfen oder so.. die funktion "SqlData.setMachineOnline(SsenderId);" wird automatisch angetoßen sobald per socketverbindung die nachricht kommt.

irgendwo muss ich auch noch die machinenid übergeben die dann online bzw offline geschaltet werden muss.


> public class CheckOnline extends Thread  {
> 
> private int time = 30; // sekunden
> private boolean running = false;
> ...



vielen dank euch. 
ich hoffe ihr könnt mir weiterhelfen.


----------



## Guest (15. Aug 2007)

ich habe ja sozusagen keine checkklasse, da das setmachine online oder delmachineonline ja nur angeschmissen wird wenn die nachricht ankommt.

so sieht das aus :


```
if(level.equals("<135>")){
		   level = "Debug";
	   }
	   
	   if(level.equals("<199>")){
		   level = "Machine-Online";
		  System.out.println("Maschine: "+SsenderId+","+Stype+" online");
		  
		  try {
			 
			  CheckOnline mtArray[]  = new CheckOnline[5]; 

			  for (int i = 0; i<Statusdaten.size(); i++){ 
			 // mtArray[i] = new CheckOnline(sql[i]); //  in sql sind deine abfragen auf die Datenbank gekapselt 
			  mtArray[i].start();
			  
			  } 
			SqlData.setMachineOnline(SsenderId);
		} catch (SQLException e) {e.printStackTrace();}
	   }
	   if(level.equals("<198>")){
		   level = "Machine-Offline";
		  System.out.println("Maschine: "+SsenderId+","+Stype+" Offline");
		  try {
			SqlData.delMachineOnline(SsenderId);
		} catch (SQLException e) {e.printStackTrace();}
	   }
```

much thx


----------



## Guest (15. Aug 2007)

habe es noch weiter umgeschhrieben.:


```
if(level.equals("<199>")){
		   level = "Machine-Online";
		  System.out.println("Maschine: "+SsenderId+","+Stype+" online");
		  
		  //SqlData.setMachineOnline(SsenderId);
		  
		  CheckOnline mtArray[]  = new CheckOnline[Statusdaten.size()]; 
		  for (int i = 0; i<Statusdaten.size(); i++){ 
		  mtArray[i] = new CheckOnline(Statusdaten.get(i).m_sender_id); 
		  mtArray[i].start();
		  } 
		
	   }
```


und:


```
public class CheckOnline extends Thread  {
	
	private int time = 30;
	private boolean running = false; 

	String SenderId;

	CheckOnline(String ssenderId ){ 
		SenderId = ssenderId;
	} 

	public void start(){ 
	   if (time < 30) time = 30; 
	   running = true;
	} 

	public void run(){ 

	   while (running){ 
	       sleepOneSec(); 
	       if (time == 15 ){  
	          if (true/*wie soll ich hier das bist du da realisieren ? weil die funktion ja nur angeworfen wird wenn die 
	          nachricht kommt  ?!?! */) { 
	          time=30; 
	        } else
				try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();} 
	       } 
	   } 
	
		try {SqlData.setMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}

	}
	 

	private void sleepOneSec(){ 
	   try 
	   { 
	       Thread.sleep(1000); 
	       time--; 
	       if (time == 0 ) running = false; 
	} 
	catch (Exception e) {} 

	}
}
```

much thx !!


----------



## Guest (15. Aug 2007)

habe alles nochma überarbeitet und hoffe das ihr mir jetzt weiterhelfen könnt.
also ich will erstma nur das es löuft. aber das tut es nicht. code sieht so aus :


```
public class CheckOnline extends Thread implements Runnable  {
	
	private int time = 30;
	private boolean running = false;
	String SenderId;
	
	public static void main(String [] args){
		
		  Thread t1 = new Thread( new CheckOnline("36965") ); 
		  t1.start();
	}

	CheckOnline(String ssenderId ){ 
		SenderId = ssenderId;
	} 

	public void start(){ 
	   if (time < 30){
		   time = 30; 
		   running = true;
	   }
	} 

	public void run(){ 

	   while (running){ 
	       sleepOneSec(); 
	       if (time < 5 ){ 
	    	   try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}   
	       	   }else{
	    	   try {SqlData.setMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
	    	   time = 30; 
	       }
	   } 
	}
	 
	private void sleepOneSec(){ 
	   try 
	   { 
	       Thread.sleep(1000); 
	       time--; 
	       if (time == 0 ){
	    	   running = false; 
	       }
	} 
	catch (Exception e) {} 

	}
}
```

das einzige was passiert wenn ich die klasse starte:

"The user operation is waiting for "Building Workspace" to complete.

dann so ein ladebalken --> 1 work items left.

dann kann ich des im hintergrund laufen lassen etc.

aber passieren tut nichts. egal wielange ich warte oder sonstiges.

hat jemand ne idee ?? danke euch !!


----------



## tuxedo (15. Aug 2007)

Du scheinst ein Eclipse-Problem zu haben.. Wenn du das Fenster nicht in den Hintergrund schickst: Verschwindet's dann in absehbarer Zeit?


----------



## Guest (15. Aug 2007)

also ich habe jetzt 3min gewartet und nichts hat sich getan. sollte wohl nicht richtig sein.

ist das denn vom quellcode her richtig ?


----------



## tuxedo (15. Aug 2007)

Kein Plan, das ist ja nicht alles. Und ich bin ja auch kein Compiler.

Hast du Eclipse mal neu gestartet und/oder ein "clean project" gemacht? Kannst du ein simples "Hello World" Codebeispiel in Eclipse starten? Oder taucht das Phänomen bei allem auf was du zu starten versuchst?

- Alex


----------



## Guest (15. Aug 2007)

nene alles andere läuft.

nur wenn ich diese klasse starte passiert das.

deswegen dacht ich vllt das was mit dem code nicht stimmt. aber ich find den fehler nicht. zumal ich noch nicht so der spezi in threadprogrammierung bin.

hmm...


----------



## tuxedo (15. Aug 2007)

Probier mal ein "clean project" (findest du im menü, da wo es auch "run" gibt).

- Alex


----------



## Guest (15. Aug 2007)

hab ich gemacht. aber leider ist es genauso wie vorher.

trotzdem danke


----------



## Guest (15. Aug 2007)

aaaaaaaaahhh.. jetzt geht gar nichts mehr....... !?!?


----------



## vodn7v (15. Aug 2007)

soooo... jetzt issts besser 

also.. es geht wieder.. hab grad meinen rechner neugestartet.
das mit dem working process ist auch weg.
funktionieren tut es aber trotzdem nicht 

ich hoffe da kann jemand nochmal drüber gucken.

vielen dank !!!


----------



## tuxedo (15. Aug 2007)

reduziere dein Codebeispiel doch mal soweit dass man es ohne deine anderen klassen ausführen kann.. und dann googelst du mal nach "debugging" und "java".

- Alex


----------



## jPat (15. Aug 2007)

```
public static void main(String [] args){
      
        Thread t1 = new Thread( new CheckOnline("36965") );
        t1.start();
       
   }
```
Bei diesem Beispiel kann es passieren, bevor der t1 gestartet ist, ist dein "Main" Thread schon wieder vorbei.
probiere doch mal :


```
public static void main(String [] args){
      
        Thread t1 = new Thread( new CheckOnline("36965") );
        t1.start();
       t1.join(); // dein MainThread wartet nun solange, bis t1 fertig ist.
   }
```


Falls du noch mehrere Thread gestartet hast, wie eingangs erwähnt wurde :



```
public static void main(String [] args){
  Thread t[] = new Thread[5]; 
  for (int i = 0; i<5; i++){
        Thread t[i] = new Thread( new CheckOnline("irgendeineNummer") );
        t[i].start();
}
  for (int i = 0; i<5; i++){
       t[i].join(); // dein MainThread wartet nun solange, bis t1 fertig ist.
}
   }
```


----------



## vodn7v (16. Aug 2007)

vielen dank schonmal. aber es funktioniert nicht.

wenn ich die main dann starte passiert nichts. habe mal überall ein " System.out.println(SenderId);" reingeschrieben.

und wenn ich die main starte dann geht das hier schonmal gar nicht los:


```
public void start(){ 
		 
		   if (time < 30){
		   time = 30; 
		   running = true;
	   }
	}
```


und dann wird "running" natürlich nicht auf "true" gesetzt und er geht in die while schleife nicht rein. 

jemand ne idee ??



danke !!!


----------



## tuxedo (16. Aug 2007)

Ich glaube ich hatte "debugging" schon erwähnt, oder ?

- Alex


----------



## vodn7v (16. Aug 2007)

ja hattest du ... hab ich auch schon  angewendet.. aber über das t.join(); geht er nicht hinaus.. da ist schluss..

warum weiss ich ja eben nicht.


----------



## tuxedo (16. Aug 2007)

Hast du mit "System.out.println()" versucht zu debuggen? Wenn ja: Google mal nach "debugging" und "eclipse".

Wenn du mit debuggen nicht dahinter kommst, dann muss dein Rechner soetwas wie einen "Unwahrscheinlichkeitsdrive" besitzen ;-)

- Alex


----------



## vodn7v (16. Aug 2007)

yeah.. es läuft 

sehr gut. 

hab nur nen kleines weiteres problem. wenn es um mehrere threads geht.
also bei :


```
public static void timer() throws InterruptedException{
		
		  Thread t[] = new Thread[Statusdaten.size()];
		  
		  for (int i = 0; i<Statusdaten.size(); i++){ 
			  Thread t[i] = new Thread( new CheckOnline("25697") ); 
		      t[i].start(); 
		} 
		  for (int i = 0; i<Statusdaten.size(); i++){ 
		       t[i].join(); // dein MainThread wartet nun solange, bis t1 fertig ist. 
		} 
	}
```

kommt er mit "Thread t_ = new Thread( new CheckOnline("25697") ); " nicht klar.. speziell darin das "t" er sagt nur. "syntax error. delete this token "i" ".

hmm.. kann man vllt kein threadarray erstellen ??

thx_


----------



## jPat (16. Aug 2007)

Hab mir das nochmals angeschaut und ... es funktioniert!  

```
public class CheckOnline extends Thread  {
   
   private int time = 30;
   private boolean running = false;
   String SenderId;
   
   public static void main(String [] args){
      
        Thread t1 = new CheckOnline("36965");
        t1.start();
        try {
			t1.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
   }

   CheckOnline(String ssenderId ){
    
	   SenderId = ssenderId;
   }

 

 public synchronized void start() {
	// TODO Auto-generated method stub
	super.start();
	 System.out.println("Start!" + time);
     if (time <= 30){
        time = 30;
        running = true;
     }
}

public synchronized void run(){
System.out.println("RUN!");
      while (running){
          sleepOneSec();
          if (time < 5 ){
             System.out.println("Hier!");
        	  time = 30;
          }
      }
   }
   
   private void sleepOneSec(){
      try
      {
          Thread.sleep(1000);
          time--;
          if (time == 0 ){
             running = false;
          }
   }
   catch (Exception e) {}

   }
}
```

Warum man super.start(); aufrufen muß ?? 
:###


----------



## jPat (16. Aug 2007)

Erst deklarieren, dann initialisieren !
Thread t[] = ...


----------



## Fatal Error (16. Aug 2007)

Du könntest auch ganz einfach den javax.swing.Timer benutzen 

Delay Time und ActionListener kannst du ihm übergeben und auch per start(); starten oder per stop(); stoppen.
im Prinzip das selbe spiel mit den threads, nur das du dich nicht darum kümmern musst.
ist sicher einfacher für dich


----------



## tuxedo (16. Aug 2007)

Wieso einfach wenn's auch umständlich geht ;-) So hat er jetzt wenigstens was dazu gelernt ...


----------



## vodn7v (16. Aug 2007)

schuuund.. sorry. 

bin noch dabei 

freude kommt da auf wenns erstma etwas läuft !


----------



## vodn7v (17. Aug 2007)

hey, bin noch bei dem thread array dabei.


```
public static  void timer(String senderId) throws InterruptedException{
		
		
 ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus();
		 
	      Thread t[] = new Thread[Statusdaten.size()];
		
		  for (int i = 0; i<Statusdaten.size(); i++){ 		  

		   t[i] = new  Thread(new CheckOnline(Statusdaten.get(i).m_sender_id));	  
		   
		} 
		  

	 for(int z=0;z<Statusdaten.size();z++){
			
			 if(Statusdaten.get(z).m_sender_id.equals(senderId)){
				 
				 if(t[z].isAlive()){
					 time = 15;
				 }else{
					 t[z].start();
				 }
				
			 }
			 
		 }


	}
```

hmm... ich möchte falls der thread schon läuft mit dieser id. das die zeit einfach auf 15 wieder hochgesetzt wird. aber irgednwie startet er einen neuen thread der dann wieder von 15 an runterzählt...


EDIT:

ausserdem läuft er wenn ich 2x den selben thread starten will ins minus... er hört dann nicht mehr auf =(
thx


----------



## vodn7v (17. Aug 2007)

nochmal der ganze code:


```
public class CheckOnline extends Thread implements Runnable  {
	
	private static int time = 15;
	private boolean running = false;
	String SenderId;
 
	

	
	public static void main(String [] args) throws InterruptedException{ 
		timer("36966");
		   }
	
	
	public static  void timer(String senderId) throws InterruptedException{
		
		 ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus();
		 
	      Thread t[] = new Thread[Statusdaten.size()];
		
		  for (int i = 0; i<Statusdaten.size(); i++){ 		  

		   t[i] = new  Thread(new CheckOnline(Statusdaten.get(i).m_sender_id));	  
		   
		} 
		  

	 for(int z=0;z<Statusdaten.size();z++){
			
			 if(Statusdaten.get(z).m_sender_id.equals(senderId)){
				 
				 if(t[z].isAlive()){
					 time = 15;
				 }else{
					 t[z].start();
				 }
			 }	 
		 }
	}
	
	

	CheckOnline(String ssenderId ){ 
		SenderId = ssenderId;
		} 

	 public void start(){ 
		
	      if (time <= 15){ 
	         time = 15; 
	         running = true; 
	      } 
	   } 

	public void run(){ 
		
		start();
		
	   while (running){ 
		 
	       sleepOneSec(); 
	       if (time < 1 ){ 
	    	   try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}   
	       	   }else{
	    	   try {SqlData.setMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
	       }
	   } 
	}
	 
	private void sleepOneSec(){ 
	   try 
	   { 
	       Thread.sleep(1000); 
	       time--; 
	       System.out.println("Time: "+time);
	       if (time == 0 ){
	    	   running = false; 
	       }
	} 
	catch (Exception e) {} 

	}
}
```


----------



## jPat (17. Aug 2007)

du hast eine statische  time variable, dass heisst, diese Variable ist in allen Threads gleich ...


zum negativproblem:
prüfe: line 77
if (time <= 0 ){


----------



## jPat (17. Aug 2007)

lass die das doch mal ausgeben
if(Statusdaten.get(z).m_sender_id.equals(senderId))

noch mals zum negativ problem.
MAch dir klar wass passiert, wenn 2 Threads auf die SELBE variable zugreifen, und BEIDE "GLEICHZEITIG" in der Zeile 75 ankommen. dann ist time = -1 evtl, wenn time vorher 1 war.

evtl hilft dir volatile dabei weiter oder / und 

```
private synchronized void sleepOneSec(){
      try
      {
          Thread.sleep(1000);
          time--;
          System.out.println("Time: "+time);
          if (time == 0 ){
             running = false;
          }
   }
   catch (Exception e) {}

   }
```


----------



## vodn7v (17. Aug 2007)

k besten dank. das mit dem static habe ich geändert. 

wenn ich : 


```
if (time <= 60){ 
	         time = 60; 
	         running = true; 
	      }
```

nicht das <= mache dann fängt er nicht an zu laufen. aber seitdem das static raus ist geht er auch nicht mehr ins minus. mein problem ist jetzt das wenn ich jetzt die timer funktion öfter starte dann macht er immer wieder einen neuen thread und setzt nicht die zeit einfach hoch wie er das soll.


----------



## jPat (17. Aug 2007)

```
if(t[z].isAlive()){
                time = 15;
             }else{
                t[z].start();
             }
```

Hier werden imm neu thread gestartet, da du diese Threads auch immer wieder neu erschaffen läßt...
(einige zeilen vorher)


```
Thread t[] = new Thread[Statusdaten.size()];
      
        for (int i = 0; i<Statusdaten.size(); i++){        

         t[i] = new  Thread(new CheckOnline(Statusdaten.get(i).m_sender_id));    
         
      }
```

Ich finde deine herangehensweise auch nicht so gut, da du die Timer Funktion static gemacht hast.

Mach dir die folgenden Klassen:
 1. Main -> nur die main Methode 
 2. ThreadVerwaltung, wo deine timer Methode drin ist, und auch das Thread - Array.
 3. deine ThreadKlasse.

es wird ein wenig übersichtlicher dadurch.

In einer Statischen Methode werden alla Variablen die du dort benutzt, aßer die Statischen, neu erschaffen. Das ist dein problem, da du, wenn die timer Methode verlässt, alle Thread nicht mehr zu fassen bekommst. 

Gruß


----------



## vodn7v (17. Aug 2007)

alles klar werd ich so einrichten. vielen dank schonmal.

eine frage habe ich aber noch zu diesem beispiel:


```
Code: 
 

if(t[z].isAlive()){ 
                time = 15; 
             }else{ 
                t[z].start(); 
             }
```

ich hab mir das so vorgestellt das obe in der schleifen meinetwegen 5 threads erstellt werden.

jedem thread ist eine id zugeweisen. 

in dieser schleife:


```
for(int z=0;z<Statusdaten.size();z++){
			
			 if(Statusdaten.get(z).m_sender_id.equals(senderId)){
				 
				 if(t[z].isAlive()){
					 time = 60;
				 }else{
					 t[z].start();
				 }
			 }	 
		 }
```

sucht er ja die stelle heraus an der die senderid steht die gerade gesendet wurde. also auch den thread mit der sender id.

wenn ich über thread[].isAlive jetzt abfrage ob genau dieser thread mit der soeben gesendeten is schon läuft. dann müsste man das doch so handlen können oder ?? wenn er läuft dann setz seine zeit wieder auf 60, wenn nicht dann starte ihn.

oder sollte ich dann ein time array erzeugen das dann auch immer nur genau die zeit die dem zugeordneten thread gehört dann wieder hochgesetzt wird ??

würde das gehen ??


danke dir !!


----------



## jPat (17. Aug 2007)

```
if(t[z].isAlive()){
                time = 15;
             }else{
                t[z].start();
             }
```
Zu deiner Frage:
Das Array wird immer wieder neu erzeugt, dahe kann dieser Thread ja nicht schon laufen.



Evtl soltest du deine Threads in ein Hashtable hineinpacken, dann weißt du immer, ob der schon mal gestartet wurde oder noch läuft oder überhaupt schon erzeugt wurde. 

beispiel:


```
Hashtable<String,Thread> threadHT = new Hashtable<String,Thread>();
threadHT.put("DeineID",new Thread(ID).start()); // Erzeugen + hinzufügen +Starten ...

if (threadHT.get("deineID") == null) // -> Diese ID Existiert nicht -> Thread wurde noch nicht erzeugt
if (threadHT.get("deineID").isAlive()) // Dein Thread läut .... 
// andernfalls ist er gestoppt .....
```

Dies soltest du in deiner umgebauten Form übernehmen.
 #
Gruss


----------



## Guest (17. Aug 2007)

Warum so kompliziert? Ein einfacher Timer, gekapselt in einer Hilfsklasse wäre dafür vollkommen ausreichend und 
weniger fehleranfällig als die ganze Thread-Akrobatik hier.

Irgendeine Hilfsklasse, die z.B. dieses Interface implementiert und dabei Timer/TimerTasks verwendet
	
	
	
	





```
public interface MyTimer
{
   /*
    * Task hinzufügen.
    *
    * @param id Id des Tasks
    * @param timout Zeit bis zur Ausführung des Tasks in Millisekungen
    * @param runnable Auszuführende Aktion
    */
   void addTask(String id, long timeout, Runnable runnable);

   /*
    * Task mit gegebener Id zurücksetzen. Timer beginnt von vorne.
    *
    * @param id Id des Tasks
    */
   void reset(String id);

   /*
    * Task mit gegebener Id abbrechen und entfernen.
    *
    * @param id Id des Tasks
    */
   void cancel(String id);
}
```


----------



## vodn7v (30. Aug 2007)

hallo,
ich hatte mit dieser sache erstmal pause gemacht und mich anderen aufgaben zugewendet.

jetzt sitze ich seit 2 tagen wieder hier dran. aber ich fühle mich überfordert.
es will einfach nicht so wie ich es will.

so sieht es im moment aus. ich hoffe jpat oder andere können mir nochma helfen. wäre sehr sehr dankbar darüber.


```
public class CopyOfCheckOnline extends Thread implements Runnable  {
	
	private int time = 360;
	private boolean running = false;
	String SenderId;
	String Status_;
	
	CopyOfCheckOnline(String ssenderId,String status ){ 
		SenderId = ssenderId;
		 Status_ = status;
		} 
	
	public  void timer(String senderId,String Status) throws InterruptedException{
				
		
	   ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus();
		 
		Thread t[] = new Thread[Statusdaten.size()];

		Hashtable<String,Thread> threadHT = new Hashtable<String,Thread>(); 
		
		for(int p=0;p<Statusdaten.size();p++){
			
			 if(Statusdaten.get(p).m_sender_id.equals(senderId)){
			
					 threadHT.put(Statusdaten.get(p).m_sender_id,t[p]);
					 
					 if (threadHT.get(senderId) == null){

						 	t[p].start();
					 }
					 	 	
					 if (threadHT.get(senderId).isAlive()){
						    time = 60;
					 }
			 }}
		
		try {SqlData.setMachineOnline(SenderId,Status_);} catch (SQLException e) {e.printStackTrace();}
	}	

	
	 public void start(){ 
		
	      if (time <= 360){ 
	         time = 360; 
	         running = true; 
	      } 
	   } 

	public void run(){ 
		
		start();
		
	   while (running){ 
		 
	       sleepOneSec(); 
	       
	       if (time < 1 ){ 
	    	   try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}   	
	       }
	   } 
	}
	 
	private void sleepOneSec( ){ 
	   try 
	   { 
	       Thread.sleep(1000); 
	       time--; 
	       System.out.println("Time: "+time);
	       if (time == 0 ){
	    	   running = false; 
	       }
	} 
	catch (Exception e) {} 

	}
}
```

wenn ichs starten will bekomme ich diese fehlermeldung:"Fehler: java.lang.NullPointerException"


vielen dank !!


----------



## tuxedo (30. Aug 2007)

Ja und wir sollen jetzt hellsehen wo der Fehler auftritt? 
Wie wär's wenn du einen Stracktrace des Fehlers postest und die mit dem NullPointer in zusammenhang stehende Zeile nennst (nicht nur die nummer, sondern was drin steht)? 

Was eine NullPointerException ist weißt du, oder? 

Gruß
Alex


----------



## vodn7v (30. Aug 2007)

hmm.. so richtig sicher bin ich mir nicht. aber würds gern wissen  
ist das das irgednwas bei der parameterübergabe schiefläuft ?
danke


----------



## tuxedo (30. Aug 2007)

Hallo? Ich habs doch eben erklärt: Wir können nicht Hellsehen wo in den 80 Zeilen die du gepostet hast die Exception auftritt.

Oder vergisst du Satz 1 und 2 wieder wenn du den dritten Satz gelesen hast?

Zur Sache mit der NullPointerException:

Ein Beispiel:


```
String a = "hallo";
```

Der String ist NICHT NULL und hat eine Länge von 5.


```
String a = "";
```

Der String ist NICHT NULL und hat eine Länge von 0 (kein Zeichen im String, sprich leerer String).


```
String a;
```

Wenn du diese Variable jetzt irgendwie abfrägst, bevor du ihr einen Wert zugewiesen hast (egal ob "hallo" oder ""), dann bekommst du eine NullPointerException.

Ergo: Bevor man Variablen benutzt, muss man sie initielisieren.

So, und als letzten Satz, damit du dir's für den nächsten Post merken kannst:

Poste bitte die komplette Fehlermeldung mit allem drum und dran (angabe der Zeilen etc..) und dann schreib dazu welche Zeile (also der Code in der Zeile, nicht die Nummer) den Fehler verursacht hat.


----------



## vodn7v (30. Aug 2007)

du wirst mich jetzt wahrscheinlich fuer total bekloppt halten. aber ich habe keine ahnung wie ich das mache.
in der konsole steht nichts ausser dem was ich oben geschrieben habe.


ich bin mal im debugmodus durchgegangen. und er hört an dieser stelle auf


```
threadHT.put(Statusdaten.get(p).m_sender_id,t[p]);
```

und sagt dann "resource not found"

ich hoffe das das weiterhilft. ansonsten wäre es nett wenn du mir nen kleinen einführungskurs ins stacktracing geben könntest.

vielen dank !


----------



## tuxedo (30. Aug 2007)

Also... generell:

Ein Catch-Block eines "Try's" sollte entweder ein "e.printStackTrace();" enthalten, oder irgend etwas anderes zur korrekten Fehlerbehandlung. Wenn du nicht weißt wie du den Fehler behandeln sollst: Lass "e.printStackTrace();" drin stehen, dann sieht man wenigstens den Fehler. 

Da du kein lauffähiges Minimalbeispiel gepostet hast, und den Rest des Prpgramms vorenthälst, kann ich dir nicht sagen wo der Fehler liegt dass dir kein korrekter StackTrace ausgegeben wird.


```
threadHT.put(Statusdaten.get(p).m_sender_id,t[p]);
```

Wenn du Eclipse benutzt kannst du, im Debug-Modus, variablen und Objekte während der Ausführung markieren und im Kontextmenü (rechte Maustaste auf die markierte Variable) "watch" (im deutschen wohl "beobachten") auswählen. Dann siehst du welchen Wert die Variable hat.

Falls du ne andere IDE benutzt: Da muss es etwas ähnliches geben.

In der geposteten Codezeile steckt folgendes drin:

1) Statusdaten
2) Statusdaten.get(p)
3) Statusdaten.get(p).m_sender_id
4) t[p]

So, analysieren wir das mal:

Statusdaten hast du bereits initialisiert:


```
ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus();
```

das wirds also nicht sein.

Statusdaten.get(p) ... Das ist das was deine get-Methode bei der initialisierung von sich gegeben hat. Da die Schleife begonnen wird, ist da also auch was in Statusdaten drin...

p ist ein Zähler, sollte also auch noch keine Probleme bereiten.

Aber was ist mit Statusdaten.get(p).m_sender_id ?? ist m_sender_id eine Public-Variable? Ist die vielleicht "null" ? 

Wenn du schon debuggst, dann kannst du das ja mal "richtig" schritt für schritt durchgehen und auch die Variablen und Objekte checken.

- Alex


----------



## jPat (30. Aug 2007)

```
threadHT.put(Statusdaten.get(p).m_sender_id,t[p])
```

Du hast vergessen, deine t[p] zu füllen!


```
if (threadHT.get(senderId) == null){

                      t[p].start();
                }
                       
                if (threadHT.get(senderId).isAlive()){
                      time = 60;
                }
```

So kannst du das auch nicht machen, da wenn erstes null ist , dann bleibt es auch weiterhin null!!


evtl:


```
if (threadHT.get(senderId) == null){  // gibt es keinen Thread
                       t[p] = new CopyOfCheckOnline (Statusdaten.get(p).m_sender_id) // dann erschaffe einen
threadHT.put(Statusdaten.get(p).m_sender_id,t[p]);  // ab in die HJashtable damit
                      t[p].start(); // und starte ihn!
                }
```



```
if (threadHT.get(senderId).isAlive()){
                      time = 60;
                }
```

heißt soviel wie: 
falls du noch da bist, also läufst, setze (bei wem auch immer) time auf 60.

Wie oben schon geschrieben, geht das so nicht.

Schreib die ne Main, eine Verwaltung für die Threads in einer EXTRA-Klasse wo die timer-Methode drin ist, UND eine ThreadKlasse...


----------



## tuxedo (30. Aug 2007)

Oh man, ich muss schon n  bisschen Blind gewesen sein. Ist ja offensichtlich... 

Den Fehler hab ich früher auch gemacht: Ein Array angelegt und vergessen die Array-Zellen zu initialisieren/instanziieren.


----------



## vodn7v (31. Aug 2007)

ich fühle mich grade echt so als hätte ich noch nie programmiert .. 
ich hoffe ihr helft mir trotzdem. bin so froh wenn ich das thread problem hinter mir habe.
vielen dank !!

meine main klasse:


```
public class testmain extends Thread implements Runnable { 
	
 public static void main (String [] args) throws InterruptedException{
	 
	 String id = "36965";
	 String status_ = "2";
	 CopyOfCheckOnline bla = new CopyOfCheckOnline(id,status_);
	 
	 bla.timer(id,status_);
	 
 }
}
```

meine Timer klasse:


```
public class Timer extends Thread implements Runnable  { 
    
	   private int time = 360; 
	   private boolean running = false; 
	   String SenderId; 
	   String Status_; 
	    
	   Timer(String ssenderId,String status ){ 
	      SenderId = ssenderId; 
	       Status_ = status; 
	      } 
	    
	    
	    public void start(){ 
	       
	         if (time <= 360){ 
	            time = 360; 
	            running = true; 
	         } 
	      } 

	   public void run(){ 
	       
	      start(); 
	       
	      while (running){ 
	       
	          sleepOneSec(); 
	           
	          if (time < 1 ){ 
	             try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}       
	          } 
	      } 
	   } 
	    
	   private void sleepOneSec( ){ 
	      try 
	      { 
	          Thread.sleep(1000); 
	          time--; 
	          System.out.println("Time: "+time); 
	          if (time == 0 ){ 
	             running = false; 
	          } 
	   } 
	   catch (Exception e) {} 

	   } 
	}
```

die threadklasse:
	
	
	
	





```
public class CopyOfCheckOnline extends Thread implements Runnable  { 
    
	   String SenderId; 
	   String Status_; 
	    
	   CopyOfCheckOnline(String ssenderId,String status ){ 
	      SenderId = ssenderId; 
	       Status_ = status; 
	      } 
	    
	   public  void timer(String senderId,String Status) throws InterruptedException{ 
	                   
	      ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus(); 
	      	       
	      Thread t[] = new Thread[Statusdaten.size()]; 
	      
	      for(int e=0;e<Statusdaten.size();e++){
	    	  t[e] =  new CopyOfCheckOnline (Statusdaten.get(e).m_sender_id, Status_);
	      }
	      
	     Hashtable<String,Thread> threadHT = new Hashtable<String,Thread>(); 
	     
	     
	      for(int p=0;p<Statusdaten.size();p++){ 
	    	  	          
	          if(Statusdaten.get(p).m_sender_id.equals(senderId)){ 
	          

	                if (threadHT.get(senderId) == null){  
	                	 t[p] = new Thread(new Timer(Statusdaten.get(p).m_sender_id,Status_));  
	                      threadHT.put(Statusdaten.get(p).m_sender_id,t[p]);   
	                      t[p].start();
	                }

	             //   if (threadHT.get(senderId).isAlive()){ 
	              //  	   time = 60; 
	              //  } 
	          }} 
	       
	      try {SqlData.setMachineOnline(SenderId,Status_);} catch (SQLException e) {e.printStackTrace();} 
	   }    

}
```

das läuft jetzt soweit auch .
ich weiss nur nicht wie ich das mit der zeit machen soll.

also falls id vorhanden --> setze zeit wieder auf 60

danke

EDIT:

ich hab grad ma asuprobiert.. also wenn ich mehrmals die gleiche id schicke dann startet er trotzdem mehere threads und nicht nur fuer jede id einen einzigen .. =/


----------



## tuxedo (31. Aug 2007)

Das ganze wirkt irgendwie immer verstrickter:

1) Die TestKlasse muss nicht von Thread ergeben und muss auch kein Interface implementieren
2) Wo startest du die ganzen Threads überhaupt?
3) Das ganze wäre einfacher zu verstehen wenn du dein Programm kommentieren würdest. In einem halben Jahr weißt du nämlich selbst nichtmehr was wie und vor allem warum funktioniert
4) Wieso bastelst du in der "timer" Methode ein Thread-Array, initialisierst es mit Instanzen von CopyOfCheckOnline und überschreibst den Inhalt unten wieder mit Instanzen von "Timer" ??

Irgenwie ist das stark verwirrend, oder ich schnall nicht was du da machst.


----------



## vodn7v (31. Aug 2007)

also ich kann das ja mal kurz erklären.

ich kriege per udp verbindung lognachrichten geschickt. alle 20 sekunden oder so gibts ne nachricht von einer maschine die mir damit signalisiert das sie "online" ist.

die maschine schickt dabei jedes mal ihre maschinen id sowie ihren status ( online,error) mit.

ich möchte jetzt wenn eine nachricht ankommt in meiner datenbank den status der maschine setzen. 
wenn man länger als 20 sekunden nichts mehr gehört hat geht sie offline. ansonsten soll der timer wieder hochgesetzt werden und ggf der status verändert werden.

das ganze sollte mit 10-20 maschinen gehen.

gestartet wird das ganze hier :


```
if(level.equals("<199>")){
		   level = "Machine-Online";
		  System.out.println("Maschine: "+SsenderId+","+Stype+" online");
//		SqlData.setMachineOnline(SsenderId);
		  
		CopyOfCheckOnline CheckOnline = new CopyOfCheckOnline(SsenderId,Status);
		
		// System.out.println("status: "+Status);
		 
			  try {CheckOnline.timer(SsenderId,Status); } 
			  
			  catch (InterruptedException e) {e.printStackTrace();}

	   }
```
Der code befindet sich in der klasse die die nachricht empfängt und in ihre einzelheiten aufteilt. dann übergibt sie der Checkonlineklasse die maschinen-id sowie den empfangenen status.

dann soll ein thread gestartet werden der 20 sekunden runter zählt. wenn die gleiche maschine wieder eine nachricht schickt wird der status geändert, und die zeit wieder auf 20 gesetzt.

das ganze fuer jede maschine einzeln.

so sollte das ganze aussehen


da ich nicht so die ahnung von threadprogrammirerung habe versuche ich einfach das umzusetzen was jPat mir immer sagt.
aber anscheind klappt das nicht so ganz .. zumidest kommen wir immer einen schritt weiter.

es muss halt gelöst werden... egal wie.. und würde ich euch nicht haben würde ich das glaube ich nie hinbekommen.


EDIT:

zu pukt 4: da gebe ich dir recht. das macht keinen sinn.. ist mir aber nicht aufgefallen weil es funktioniert hat. danke dir.


----------



## jPat (31. Aug 2007)

Also:

 Main Klasse:
diese Klasse dient NUR zum erstellen deiner Verwaltung, UND zum Fragen in der Verwaltung, ob Irgendwas Mit den Threads ist. sonst NIX.

```
class Main {

public static void main(String args){
Verwaltung v = new Verwaltung();
v.init();
// hier wird die Verwaltung bemüht, um in der Liste zu schauen, was mit den Thread grad so los ist. (Jede sekunde)
while(true){
try{
Thread.sleep(1000); //Warte 1 secunde (hat nix mit deinen Threads zu tun ist für den MAIN-THREAD!!) 
v.ckeckThreads();
}catch(Exception e){syso(e.printStackTrace()) }
}
}
}
```

deine Verwaltungsklasse dient zum Verwalten der Threads und natürlich zum starten der Threads.

```
class Verwaltung {
Hashtable<String,CheckOnline> threadTable = new Hashtable<String,CheckOnline>();
ArrayList<ReturnSqlMachineStatus> Statusdaten;
Thread t[]; 

// in dieser Methode werden ALLE Threads gestartet!! und in die HT geschrieben. Diese Methode solltest du für weiter überprüfungen NICHT ändern.
public void init(){ 
 Statusdaten = SqlData.getSqlDataStatus();
 t[] = new Thread[Statusdaten.size()];  
      for(int p=0;p<Statusdaten.size();p++){                                 
              t[p] = new Thread(new Timer(Statusdaten.get(p).m_sender_id,Status_)); 
              threadTable .put(Statusdaten.get(p).m_sender_id,t[p]);   
              t[p].start();
}
public void ckeckThreads(){

for (int i =0, i<Statusdaten.size(); i++){
if ( threadTable.get(Statusdaten.get(p).m_sender_id) == null ) {sysout("Der existiert gar nicht:  "+ i)}
else if ( threadTable.get(Statusdaten.get(p).m_sender_id).runnable=false ) {sysout("Der ist fertig!!:  "+ i)}
if ( threadTable.get(Statusdaten.get(p).m_sender_id).runnable==truel ) {sysout("der läuft noch:  "+ i)}
}



}

}
```

deine Checkonline Klasse erweitert die Thread-Klasse. In diesem beispiel wartet jeder Thread 60 sekunden, macht dann die SqlData.delMachineOnline() Methode und geht zu ende.


```
class CheckOnline extends Thread{
int time = 0;
boolean running = false
public void start(){
          super.start();
            if (time <= 10 || running==false){
               time = 10;
               running = true;
            }
         }

      public void run(){
          
         while (running){
          
             sleepOneSec();
              
             if (time < 1 ){
                try {SqlData.delMachineOnline(SenderId); running=false;  } catch (SQLException e) {e.printStackTrace();}       
             }
         }
      } 
private void sleepOneSec( ){
         try
         {
             Thread.sleep(1000);
             time--;
             System.out.println("Time: "+time);
             if (time == 0 ){
                running = false;
             }
      }
      catch (Exception e) {}

      } 

}
```

Du mußt dir klarmachen, das der Mainthread für dich die Aufgabe übernehmen muß, in die Verwaltung zu schauen, was mit den Threads ist. 

In deinem Code wird soll ja für Jeden CheckOnlineThread ein Weiterer Thread zur Prüfung des Status erschaffen werden. Das ist eine Ebene zu Tief ....

Ich hoffe es klappt nun mit dem Verständnis. Der code ist nicht getestet, sollte aber von der Stuktur funktionieren.

Gruß


----------



## vodn7v (3. Sep 2007)

@ jPat echt vielen Dank fuer deine Bemühungen.

versuche das grade alles umzuschreiben, weil irgednwie entspricht das noch nicht so ganz dem sinn meiner vorstelleung. oder ich habs nicht verstanden 

weil ja nicht alle threads gestartet werden sollen. sondern nur der von dem ich per socket ne nachricht bekomme und der dann den thread anstoßen soll. (der status ist dabei variable)

also zb.

alle threads aus. dann kommt ne message mit  (Id=25696,Status=3) --> dann soll der thread gestartet werden, timer soll runter laufen. kommt nacht 5 sekunden jetzt aber schon wieder ne neue message (Id=25696,Status=2)
soll nur der Status geändert werden + zeit wieder hochgesetzt werden und dann wieder runterlaufen.

das ganze soll dann bei allen maschinen so laufen.

falls dann bsp 30 sekunden gar keine message kam, wird der status automatisch auf 0 gesetzt ( bei der maschine die keine meldung mehr bekommen hat)

ich versuche das jetzt so umzubauen. falls du noch tipps hast. immer her damit 

vielen dank schonmal.

hier ist noch der code mit dem ich die messages empfange. vllt hilft das ja weiter.



```
public class GetLogData extends Thread implements Runnable { 
	
	
	static String SenderId = null;
  
	public void startLog(){
		Thread t1 = new Thread( new GetLogData("36965")  ); 
        t1.start(); 
	}
	
	public GetLogData(String ssenderId ){ 
		 this.SenderId = ssenderId;
		} 
	
    public void run (){ 
      try{     
           byte  buffer[] = new byte[0xffff]; 

          DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 
          DatagramSocket socket = new DatagramSocket(SqlData.getPort()); 
          
           while (true) 
            { 
            socket.receive(packet); 

            int    len      = packet.getLength(); 
                    buffer   = packet.getData(); 
                     
            String   frage    = new String(buffer, 0, len); 

            System.out.println("Anfrage von: " + packet.getAddress() + 
                                  " am Port " + packet.getPort() + " empfangen: " + frage ); 

            SplitLdata.Split(packet.getAddress(),packet.getPort(),frage);
        	}
          } 
       catch ( Exception e ) 
          { 
            System.out.println("Fehler: " + e); 
          } 
   }
}
```

In SplitData wird die message aufgesplittet und "senderId" sowie "status" an die threadfunktion übergeben.

EDIT: bin auch gern fuer andere lösungen offen. also falls das ganze ohne threads oder sowas geht. dann nehm ich aucg gerne solche vorschläge an  (threads mag ich seit diesem thema nicht mehr   )

vielen dank !!


----------

