• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

[Java] zeitabhängige Vorgänge

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
Hallo,

ich suche eine Möglichkeit mit Java eine Schleife, die zur gesamten Zeit des Programmes läuft, und nach einer gewissen Zeit (z.B. 5min) den Schleifenkörper ausführt.
Also soetwas wie Mail es bei dem Abfragen der Mails tut.
Gibt es da eine am besten plattformunabhängige Lösung?
 

Dadelu

Reinette Coulon
Registriert
06.07.05
Beiträge
939
Hi, mal schauen ob ich dich richtig verstanden habe...

Alos ich würde dieses Problem so lösen. Baue einfach um den, nach x minuten, auszuführenden Code zählschleife.. Somit kannst du bestimmen nach wie lange der Inhalt ausgeführt werden soll. Um die Zählschleife schreibst du eine "Endlose" Schleife welche immer läuft wenn das Programm aktiviert ist. Der Inhalt dieser schleife ist blos die Zählschleife und diese wird ja nid immer ausgeführt. Falls ich deine Problematik richtig verstanden haben sollte, könnte dir das vieleicht weiterhelfen, ansonsten probiere ich es dann noch mal ;)
 

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
sicher, aber wie schreibe ich eine Zeitzähl-Schleife?
 

Dadelu

Reinette Coulon
Registriert
06.07.05
Beiträge
939
Also ich probiere es einmal so einfach wie möglich zu erklären.

Du könntest die ganze Sache mit dem Thema Threading steuern. Je nach Problem/Anforderung könnte dies eine sehr gute Möglichkeit sein. Jedoch ist dies nicht gerade einfach, meiner Meinung nach. Falls du es mit einem Thread lösen willst, könntest du die gesamte Architektur so lösen, dass du dann den einten Thread (was in diesem Fall deine Schleife wäre) zu "schlafen" bringst,sprich THREAD.sleep(xxZeitxx).

Weitere gute Informationen findest du hier: www.java-forum.org
 

Thof

Gast
Code:
try {
  // 5 Minuten abwarten
  // = 300 Sekunden
  // = 300.000 Millisekunden
   Thread.sleep(300000);
}
catch(Exception e) {}

Thread.sleep(long millis) bewirkt, das der laufende Thread für die angegebene Zeit (in Millisekunden) unterbrochen wird. Der ganze Spaß muss in einen try-catch-Block, da der Vorgang z.B. bei einem Programm-Abruch eine Exception werfen kann.

Wenn du wirklich einen nebenläufigen Prozess aufbauen willst, der z.B. in regelmäßigen Zyklen etwas durchführt solltest du auf Threads zurückgreifen. Das könnte dann wie folgt aussehen:

Code:
class Prozess extends Thread {

   private String msg;

   public Prozess(String ausgabe) {
      msg = ausgabe;
   }

   public void run() {
      while(!interrupted()) {
         try {
            Thread.sleep(300000);
            System.out.println(msg);
         }
         catch(Exception e) {}
      }
   }
}

Um den Thread zu verwenden kannst du wie folgt auf ihn zugreifen:

Code:
...
Prozess p = new Prozess("Ausgabe...");
p.start();
...

Was passiert?
Nachdem der Thread gestartet wurde, wird er - bis er irgendwann gestoppt wird - alle 5 Minuten die Textzeile "Ausgabe..." in der shell ausgeben.


Hier noch ein bisschen Hintergrund zum Schmökern:
1.) Java API Dokumentation (java.lang.Thread):
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Thread.html

2.) Java Tutorial - Multithreading:
http://java.sun.com/docs/books/tutorial/essential/threads/index.html


Gruß,
Thomas.
 

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
danke euch beide, ich werde mir die Links durchlesen und es versuchen. :)
 

Dadelu

Reinette Coulon
Registriert
06.07.05
Beiträge
939
@Thof

Gute und übersichtlich Darstellung! Tip Top

Jedoch noch einen kleinen Hinweis. Die ganze Sache mit den Threads ist zwar super, aber praktisch die gesamte Applikation muss darauf abgestimmt werden. Du kannst dann zum Beispiel nicht einfach auf den Inhalt des Thread's zugreifen, wenn die ganze Sache nicht sinchronisiert ist (synchronized)... Aber eben.. Guck dir die Links durch und du wirst danach sicherlich mehr wissen ;)
 

Thof

Gast
Dadelu schrieb:
Die ganze Sache mit den Threads ist zwar super, aber praktisch die gesamte Applikation muss darauf abgestimmt werden. Du kannst dann zum Beispiel nicht einfach auf den Inhalt des Thread's zugreifen, wenn die ganze Sache nicht sinchronisiert ist (synchronized)... Aber eben.. Guck dir die Links durch und du wirst danach sicherlich mehr wissen ;)

Stimmt... (hätte ich jetzt vergessen)

Wenn du mit Threads arbeitest, solltest du darauf achten, dass alle Methoden, die "am Stück" durchlaufen werden sollen synchronisiert sind.

Hier ein Beispiel:

1.) Irgendein verarbeitbares Objekt:

Code:
class MeinObjekt {

   private int zaehler;

   public MeinObjekt(int startWert) {
      zaehler = startWert;
   }

   public void machEtwas() {
      // irgendetwas mit der Variablen zaehler machen
      int alterWert = zaehler;
      zaehler = 5;
      zaehler = 7;
      zaehler = 9;
      zaehler = 1;
      zaehler = 10;
      zaehler = 12;
      zaehler = alterWert + 1;
   }

   public int getZaehler() {
      return zaehler;
   }
}


2.) Thread-Klasse:

Code:
class MeinThread extends Thread {

   private MeinObjekt mo;

   public MeinThread(MeinObjekt objekt) {
      mo = objekt;
   }

   public void start() {
      while(!interrupted()) {
         try {
            Thread.sleep(10000) {
            System.out.println("Aktueller Stand: " + mo.getZaehler());
         }
         catch(Exception e) {}
      }
   }
}


3.) Code, die beides verwendet:

Code:
...
MeinObjekt mo = new MeinObjekt(1);
MeinThread mt = new MeinThread(mo);
// Endlosschleife
while(true) {
   mo.macheEtwas();
}
...

Was sollte passieren:
  • Bei jedem Aufruf der Methode macheEtwas() wird der zaehler im Endeffekt um 1 nach oben gezählt. Dazwischen finden irgendwelche (hier sinnfreien) Operationen mit zaehler statt.
  • Alle 10 Sekunden greift der Thread auf zaehler zu (getZaehler()) und gibt den aktuellen Stand aus... theoretisch also immer den um 1 hochgezählten Wert (bzw. der Wert, um den er eben in 10 Sekunden hochgezählt wurde)

Was tatsächlich passiert:
Der Thread greift exakt nach 10 Sekunden auf den Wert von zaehler zu. Dabei wird nicht gewährleistet, dass die Methode macheEtwas() gerade läuft. Das heißt der Wert von zaehler könnte gerade "in Bearbeitung" sein, also in unserem Beispiel einen der Werte 5, 7, 9, 1, 10 oder 12 angenommen haben... je nachdem wann der Thread zugreift. Möglicherweise greift der Thread auch im genau richtigen Moment und erwischt einen frich hochgezählten Wert...

Und weil das in etwa so ist wie Lotto spielen gibt es in Java auch eine Anweisung, mit der du sicherstellen kannst, dass der Thread erst wieder zugreifen darf, nachdem macheEtwas() komplett abgearbeitet wurde.

Die entsprechende Anweisung heißt synchronized und wird im Methodenkopf notiert:

Code:
// alt
public void macheEtwas() { ... }

// neu
public synchronized void macheEtwas() { ... }

;)
 
  • Like
Reaktionen: Wikinator

Dadelu

Reinette Coulon
Registriert
06.07.05
Beiträge
939
1A Beitrag! Genau so geht die Sache ;)
 

mullzk

Linsenhofener Sämling
Registriert
04.01.04
Beiträge
2.529
nene leute, nehmt nicht Thread.sleep(), da gehts ums blockieren des threads. funktioniert zwar, aber ist nicht der sinn der sache.

um etwas immer wieder zu starten, gibts javax.swing.timer : http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/Timer.html

wirft ein actionevent wenns so weit ist

also einfach im objekt, welches etwas regelmässig tun soll, im constructor einen timer erstellen und sich selbst als actionlistener eintragen...


[edit]und auch wenn ich davon abrate, für dieses unterfangen threads einzusetzen: die übersicht ist wirklich toll, danke...[/edit]
 

Dadelu

Reinette Coulon
Registriert
06.07.05
Beiträge
939
mullzk schrieb:
nene leute, nehmt nicht Thread.sleep(), da gehts ums blockieren des threads. funktioniert zwar, aber ist nicht der sinn der sache.

um etwas immer wieder zu starten, gibts javax.swing.timer : http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/Timer.html

wirft ein actionevent wenns so weit ist

also einfach im objekt, welches etwas regelmässig tun soll, im constructor einen timer erstellen und sich selbst als actionlistener eintragen...


[edit]und auch wenn ich davon abrate, für dieses unterfangen threads einzusetzen: die übersicht ist wirklich toll, danke...[/edit]

Jep ist auch eine gute Möglichkeit.. :D Leider verwenden wir im Geschäft, solche schei** Frameworks... Diese haben meiner Meinung nach überhaupt nichts mehr mit Java programmieren zu tun.. :(
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
@mullzk: Wiederspreche Dir nur ungerne :), aber es macht überhaupt keinen Unterschied, Thread bzw. das Interface Runnable zu verwenden, oder den Timer Task, denn siehe Doku:

Javadoc von TimerTask schrieb:
Method Detail
run

public abstract void run()

The action to be performed by this timer task.

Specified by:
run in interface Runnable

See Also:
Thread.run()

Letztlich wird ein Thread gestartet, der genau den oben so exzellent beschriebenen Vorgang ausführt.

Allerdings hat man bei Eigenimplementierung den Vorteil, daß man den Thread jederzeit wiederverwenden kann, wenn man ihn niemals tötet, komplexe Synchronisierungen (z.B. über gehashte Monitorobjekte) usw. durchführen kann, was über den TimerTask nicht geht.

Und: Thread.sleep() blockt den Thread nicht, sondern legt ihn schlafen, das heißt, falls native, wird er einfach aus dem Scheduler genommen, falls geforkt, kommt er nicht zum Zug, bis genug Luft ist. Was jederzeit passieren kann. Das ist aber auch beim TimerTask nicht anders.

Gruß,

.commander
 
Zuletzt bearbeitet:

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Ups, nicht ganz: Wenn man es sich leisten kann mit kurzen run() Methoden auszukommen, ist TimerTask wirklich besser, da alles in _einem_ Thread ausgeführt wird. Hatte ich übersehen (wäre auch für meinen assynchronen Schiet ungeeignet.. ;))

Also, sorry, mullzk,
icon10.gif
bin Dir ungerechterweise übers Maul gefahren, je nach Anwendung mag der TimerTask besser geeignet sein: Aber Achtung: um Tasks auszuführen, die das GUI verändern, ist nach wie vor ein call von SwingUtility.invokeLater(bölk) oder SwingUtility.invokeAndWait(bölkStoff) notwendig, da der TimerTask nicht vom AWT-EventDispatcher ausgeführt wird (zumindest habe ich nichts darüber gefunden)

Gruß,

.commander
 

mullzk

Linsenhofener Sämling
Registriert
04.01.04
Beiträge
2.529
commander schrieb:
@mullzk: Wiederspreche Dir nur ungerne :)
schade, ich lerne immer wieder gerne von leuten, die von java wirklich viel verstehen, und du gehörst definitiv in diese kategorie

Und: Thread.sleep() blockt den Thread nicht, sondern legt ihn schlafen, das heißt, falls native, wird er einfach aus dem Scheduler genommen, falls geforkt, kommt er nicht zum Zug, bis genug Luft ist.
siehste, schon wieder etwas gelernt. allerdings gebe ich zu, dass ich bei diesem methoden-namen eigentlich auch selber hätte drauf kommen können.

und auch wenn es schlussendlich auf das selbe hinausläuft und der eigene thread sogar vorteile bietet, würde ich starrköpfig wie ich bin, beim swing-timer bleiben, einfach weil er mir klarer erscheint.
new Timer(300000, this).start sowie die actionperformed(), sind in ihrer bedeutung eindeutig. ein eigener thread hingegen kann alle möglichen zwecke haben, das mit der zeitschlaufe sieht man erst, wenn man die run() genauer anschaut.

kosmetiküberlegungen, ich weiss, aber ich gehöre zu diesen süppeler-programmieren, die von allen möglichkeiten gerne jene nutzen, die am explizitisten meine wünsche befriedigt :p
andererseits nutze ich auch immer gerne jene möglichkeiten, die von javagöttern empfohlen werden, also werde ich mir bei meinem nächsten ähnlichen problem wohl mal der einsatz eines eigenes threads überlegen :eek:
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Wenn wir grade beim Thema sind, Danke, spreche Java fliessend, wäre übrigens an einer Cocoa-Session in der Schweiz (z.B. im Winter, wenn man sich auf die Bretter stellen kann) SEHR interessiert!!!!

Vorschuss: Auch wenn das nur für Leute interessant ist, die sich auf Java einen runterholen können:

Du hast einen Singleton in einem Server laufen, der sicherstellen muss, daß keine schreibenden und lesenden Zugriffe auf ein und das selbe Objekt (das Du aber nicht synchronisieren kannst, da es sich z.B. um ein persitentes Objekt handelt) gleichzeitig passieren, aber das muss so granular passieren, daß es bei massiv parallelen Zugriffen niemals passieren darf, daß Threads geblockt werden, die Daten anfassen, die gar nix miteinander zu tun haben.

Also: Stell Dir einen komplexen Baum von Daten vor, die assynchron geschrieben und gelesen werden können. Der "DataDescriptor" sagt Dir, wo im Baum die Daten versteckt sind, "Data" ist ein Roboter, der einen Chip zum Lachen braucht (und nicht 60 Liter Weiglathaler Bier ;) ) - ne, halt die Daten, also whatever.

Interface-Methoden:

+getData(DataDescriptor descr): Data
+setData(DataDescriptor descr, Data data): void

Implementierung:

+setData(DataDescriptor descr, Data data)

schaut so aus:
Code:
public void setData(DataDescriptor descr, Data data) {
  try {
    synchronized(xPathHashMap.get(descr).block()) {
      setzeData(descr, data);    
  }
  finally {
    xPathHashMap.get(descr).unblock()
  }
}

und die Abfrage:

Code:
+getData(DataDescriptor descr): Data

public Data getData(DataDescriptor descr) {
  try {
    synchronized(xPathHashMap.get(descr).block()) {
      return holeData(descr);
    }
  }
  finally {
    xPathHashMap.get(descr).unblock()
  }
}

Du musst dabei beachten, daß "xPathHashMap.get(DataDescriptor).block()" niemals null zurückliefert, da es sonst zu einer Laufzeitexception kommt, also sollte die HashMap geeignete Lockobjekte zurückliefern. Ausserdem sollte die Hashmap 'vergesslich' sein, also nur Softreferences verwenden, die Zugriffe darauf natürlich synchron. Beim Block wird ein Flag gesetzt, daß der Hashmap sagt, daß die Referenz nicht weggeschmissen werden darf, bei unblock() darf aufgeräumt werden. Der Returntype ist Object

Damit kannst Du gewährleisten, dass unterschiedliche Threads niemals gleichzeitig auf die gleichen Daten zugreifen, was möglich wird durch das ansonsten eher unhandliche Monitor-Konzept von Java.

btw: Hat nix oder wenig mit dem ursprünglichen Problem zu tun...
 
Zuletzt bearbeitet:
  • Like
Reaktionen: cws