# Threads



## Caruso_Nix (15. November 2004)

Hallo,
ich bin noch ein ziemlicher Neuling in Java und habe da ein Problem. 
Derzeit arbeite ich mit Threads. Nun möchte ich einen Thread nach einer bestimmten Zeit, per interrupt beenden. Aber ich weiss nicht, wie ich das realisieren kann.
Kann mir jemand helfen?
Danke Caruso


----------



## torsch2711 (15. November 2004)

Du könntest üer die TimerTask klasse gehen.

implementiert Runnable und das bedeutet, das es die Thread funktionalität hat. Kannst hier über die scheduledExecutionTime, die laufzeit festlegen. Ist die Einfachste Methode. 

Oder:

Du gehst über einen zweiten Thread, welchem du den ersten mitgibst.

Thread thread1=new Thread { implementierung des auszuführenden Threads}
pseudotimer timer1=new pseudotimer(thread1);
thread1.start();
timer1.start();


class pseudotimer extends Thread {
   Thread test;
   public pseudotimer(Thread t) {
        super();
         this.test=t;
    }   

   public void run() {
           this.sleep(<anzahl der Sekunden, die er warten soll>);
           this.test.interrupt();
   }
}


Und das wars dann.


Viel Erfolg

Torsten


----------



## Caruso_Nix (15. November 2004)

Vielen Dank,
es klappt!

Caruso


----------



## Caruso_Nix (15. November 2004)

ui, doch noch nicht.

mit einem Thread läuft es, aber was mache ich, wenn mehrere laufen? ich habe in einem anderen Thema dazu ein Semaphoren gefunden. Dieser bezieht sich allerdings auf eine globale Variable. Das nutzt mir ja nichts, da ich dann ja alle Threads stoppe, wenn der Semaphoren false ist.
Wie kann ich das geschickter machen?
caruso


```
public class Test extends Thread {
 
public static boolean semaphor;
private int i = 0;
 
public void run()
{
while(semaphor)
{
doAnything();
}
}
 
public static void startThread(Thread t){
semaphor = true;
t.start();
}
public static void stopThread(Thread t){
semaphor = false;
}
 
public void doAnything(){
System.out.println(i); 
i++;
}
 
public static void main(String[] args) {
Thread t1 = new Test();
startThread(t1);
pseudotimer timer1=new pseudotimer(t1,5);
timer1.start();
 
Thread t2 = new Test();
startThread(t2);
pseudotimer timer2=new pseudotimer(t1,2);
timer2.start();
 
Thread t3 = new Test();
startThread(t3);
pseudotimer timer3=new pseudotimer(t1,5);
timer3.start();
}
 
} 
class pseudotimer extends Thread {
Thread test;
int time;
 
public pseudotimer(Thread t, int time) {
super();
this.test=t;
this.time=time;
} 
public void run() {
try {
System.out.println("TIME");
this.sleep(1000*time);
System.out.println("TIME UP");
Test.stopThread(this.test);
}
catch ( InterruptedException ie ){System.err.println( ie );}
 
}
}
```


----------



## torsch2711 (15. November 2004)

Dann musst du etwas komplexer denken,

du erwähntest ja nur, dass du es mit einem Thread machen willst.
Natürlich gibt es die umständliche und ressourcenfressende methode zu jedem Thread einen pseudotimer aufzumachen. Ist aber nicht zu empfehlen.

Oder du machst eine Thread liste und musst in jedem thread die zeit mitspeichern wann er aufgerufen wurde und in gewissen abständen schauen, welche threads über dem aufrufzeit+zeitlimit drüber sind.

Wäre eine Möglichkeit, welche mir so spontan einfallen würde.

Müsste dann ungefähr so aussehen die Pseudotimer klasse:
public class pseudotimer{
private thread test;
private List threadlist;
public pseudotimer(Thread t, int time) {
super();
this.test=t;
this.time=time;
this.threadlist.add(thread);
} 

public addThread(Thread t) {
this.threadlist.add(t);
}

endOvertimeThreads() {
Iterator i=this.threadlist.iterator();

while (i.hasNext()) {
Thread temp=(Thread) i.item();
if (temp.getstartTime()>Calendar.getTime()) {
temp.interrupt();
}
i.next();
}
public void run() {
try {
while (true) {
System.out.println("TIME");
this.sleep(1000*time);
endOvertimeThreads();
}
}
catch ( InterruptedException ie ){System.err.println( ie );}

}
}


Grüsse

Torsten

P.S.: Keine garantie, dass der code oben 1:1 läuft, können sich fehler eingeschlichen haben, ist ja auch nur da um einen überblick zu geben, wie es laufen könnte.


----------



## Caruso_Nix (15. November 2004)

Was meinst du denn mit:

temp.getstartTime()>Calendar.getTime()

muss ich mir die Methode temp.getstartTime() noch selbst schreiben


----------



## schnuffie (15. November 2004)

...warscheinlich ja, denn torsch2711 scheint "intelligente" Threads zu meinen  :


```
public class IntelligenterThread extends Thread {
 
private long zeit = 0;
 
public IntelligenterThread() {
  super();
}
 
public void start() {
  this.zeit = System.currentTimeMillis();
  super.start();
}
 
public long getStartTime() {
  return zeit;
}
 
}
```
 
CU schnuffie


----------



## torsch2711 (15. November 2004)

jep, kann mich schnuffie nur anschliessen. War eigentlich auch im Text beschrieben.

Ich denke das ist die einzige Möglichkeit. Lass mich aber gerne von anderen Korrigieren.

Ausserdem hab ich ja nur die Pseudotimerklasse beschrieben...


----------



## torsch2711 (15. November 2004)

Caruso_Nix hat gesagt.:
			
		

> Was meinst du denn mit:
> 
> temp.getstartTime()>Calendar.getTime()
> 
> muss ich mir die Methode temp.getstartTime() noch selbst schreiben



wobei sich die Starttime aus der Startzeit des Threads und des Zeitlimits zusammensetzt, das kam nicht gut raus, ich gebe es zu.
eigentlich müsste es dann getEndTime heissen. Okay, okay, mein Fehler.


----------



## schnuffie (15. November 2004)

...eine noch ergänzende Bemerkung wäre, daß sich Threads noch lange nicht durch "start()" starten lassen und somit die Startzeit eigentlich erst mit dem Aufruf der "run()"-Methode gesetzt werden kann. :-(


----------



## Caruso_Nix (15. November 2004)

ich habe das mal ausprobiert, aber ich scheitere :-(

folgender Ablauf ist geplant:
speicher threadName und Endzeit ab
starte den Thread
----

zweiter tread überprüft alle 10 sek, ob es überfällige Threads gibt.
schaue in der Speicherung, ob Endzeit < currentTime.
wenn ja: 1. lösche den Eintrag aus der Speicherung
2. unterbreche den Task
------------------------------------------------------------------------------------

tja und hier stosse ich doch auf Probleme.
welche Speicherung sollte ich verwenden? Ich muss anfügen, rauslöschen, finden(über die Endzeit).
Bei einer Iteration kann ich ja nur (object, int) verwenden. Das Problem ist, dass die Endzeit long ist.
Hashmap kann ich nur über den Key ansprechen. Also nur den Namen...suche über die Zeit hab ich nicht hinbekommen.

Ich weiss nicht mehr weiter  
caruso


----------



## schnuffie (15. November 2004)

Für alle primitiven Variablentypen gibt's Wrapper-Klassen:


```
long l = 7L;
Long longWrapper = Long.valueOf(l);
myHashtable.put("key", longWrapper);
 
//...
 
long zahl = ((Long)myHashtable.get("key")).longValue();
```
CU schnuffie


----------



## schnuffie (15. November 2004)

Das geht natürlich mit allen Collections, also z.B. auch mit ArrayList oder HashSet, die dann keinen Key benötigen. ;-)


----------



## torsch2711 (15. November 2004)

Ich glaube du verstehst das nicht ganz, 

die Zeit soll in einer Erweiterung der Klasse thread liegen.
sprich sowas:

public class extThread extends Thread {

    private long endTime;
    private long duration;    
    public extThread(long tduration) {

      super();
      this.duration=tduration;
   }

   public void run() {
       this.endTime=System.getMilliSeconds()+this.duration;
       /*
          doit! hier der Thread code

       */

   }
  public long getEndTime() {
          return this.endTime;
  } 

}



jetzt gehst du hin und  rufst deine pseudotimer klasse auf in welcher du eine liste verwaltest mit löschen, hinzufügen etc. und addest deine Threads.


public pseudotimer(extThread t) {
     super();
      list.add(t);
}

in der run machst du folgendes:

public void run() {
         while(true) {
            thread.sleep(<anzahl der millisekunden, welche du warten willst>);
            Iterator it=list.iterator();
             while (it.hasNext()) {
                           extThread tempthread=(extThread) it.next.item();
                           if (tempthread.getEndTime()>System.getMilliSeconds()) {
                                   tempthread.interrupt();
                           }

             }
            }
}


thats it.
Ich glaube besser kann man das jetzt auch nicht mehr schreiben.....


----------



## torsch2711 (15. November 2004)

schnuffie hat gesagt.:
			
		

> Das geht natürlich mit allen Collections, also z.B. auch mit ArrayList oder HashSet, die dann keinen Key benötigen. ;-)




Hehe, okay, schnuffie war früher dran. Hab aber auch nochmal nen schönen code hingezaubert, welcher dir helfen dürfte.


----------



## schnuffie (15. November 2004)

torsch2711 und ich streiten sich schon um's Helfen...


----------



## torsch2711 (15. November 2004)

schnuffie hat gesagt.:
			
		

> torsch2711 und ich streiten sich schon um's Helfen...




Ich würd mich doch nie streiten 

Du hannebambel, du 

Nee, war ein scherz.......


----------



## schnuffie (15. November 2004)

...mir ist da noch so ein Geistesblitz  gekommen:


```
public abstract class TimeRunnable extends Runnable {
 
private long start = 0;
private long end = 0;
 
public final void run() {
start = System.currentTimeMillis();
run();
end = System.currentTimeMillis();
}
 
public abstract boolean run();
 
public long getStart() {
return start;
}
 
public long getEnd() {
return end;
}
 
}
```
 
Ableitung:


```
public class MyTimeRunner extends TimeRunnable {
 
public boolean run() {
	System.out.println("http://www.webnobis.com");
	return true;
}
 
}
```
 
Verwendung:


```
TimeRunnable runner = new MyTimeRunner();
Thread t = new Thread(runner);
t.start();
```
 
CU schnuffie ;-)


----------



## torsch2711 (15. November 2004)

Hmm, das löst aber sein problem nicht, da er ja alle threads die eine gewisse laufzeit überschreiten, sprich die startzeit des Threads + die laufzeit nicht einhalten, erzwingen will, dass sie beendet werden, du lässt sie laufen und schaust am ende nach wie lange sie gelaufen sind. Bringt ihm hier herzlich wenig, dann brauch er sie auch nicht mehr abschiessen.



Grüsse

Torsten


----------



## schnuffie (15. November 2004)

...man müßte die Threads bei einem "Haupt-Thread" registrieren und diesen "Haupt-Thread" ständig laufen lassen und checken, wie lange die anderen Threads bereits laufen:


```
public class TimeThread extends Thread {
 
private long start;
 
public TimeThread(Runnable r) {
	super(r);
}
 
public void start() {
	start = System.currentTimeMillis();
	super.start();
}
 
public long getRuntime() {
	return System.currenTimeMillis() - start;
}
 
}
 
 
 
public class Runner extends Thread {
 
private List runner;
private List list = new ArrayList();
private long maxTime;
 
public Runner(List runner, long maxTime) {
	super();
	this.runner = runner;
	this.maxTime = maxTime;
}
 
public void start() {
	if (runner != null && !runner.empty()) {
	 TimeThread t;
	 Iterator it = runner.iterator();
	 while (it.hasNext()) {
		t = new TimeThread((Runnable)it.next());
		list.add(t);
		t.start();
	 }
	}
}
 
public void run() {
	while (!list.empty()) {
	Iterator it = list.iterator();
	TimeThread t;
	while (it.hasNext()) {
	 t = (TimeThread)it.next();
	 if (t.getRuntime() > maxTime) {
		t.interrupt();
		list.remove(t);
	 }
	}
	try {
	 Thread.sleep(1000);
	}
	catch (InterruptedException ie) {}
	}
}
 
}
```
 
CU schnuffie

Na, und wie jetzt? :suspekt:


----------



## Caruso_Nix (16. November 2004)

ui, das erschlägt einen ja . ich werde das mal ausprobieren, ob es klappt.


----------



## Caruso_Nix (16. November 2004)

mist, dass man einen eigenen Beitrag nicht löschen kann *grmpf* muss ich den letzten editieren.

Mit der Zeitüberprüfung etc. habe ich soweit hinbekommen. Allerdings wartet jetzt mein Prozess (den ich mit dem Thread starte) bis zum interrupt des Threads, bis er sich beendet. So nun auch nicht. Also eigentlich soll der Prozess sich abarbeiten. wenn er aber über die gewünschte Zeit benötigt, soll er abgebrochen werden. Schwierig!

in meiner "Überwachungs"Klasse lasse ich bei Überschreitung der Zeit ein *t.interrupt();* ausführen.
in der anderen Klasse, wo der Thread läuft:

```
public void run()
{ 
	Process p = Runtime.getRuntime().exec(command);
...
while ( ! isInterrupted() ). 
{
	 p.waitFor(); <-- hier nicht optimal, soll sich schon vorher beenden, wenn fertig.
}
...
}
```
 
Kann man denn in die While mitaufnehmen, "nichtInterrupt und nicht fertig"
bwz. p.destroy(); bei interrupt() oder fertig.
Ideen?
caruso


----------



## schnuffie (16. November 2004)

Thread hat eine Methode "destroy()", jedoch wird nicht garantiert, daß der Thread wirklich "zerstört" wird. 

CU schnuffie


----------

