1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

[Java] zeitabhängige Vorgänge

Dieses Thema im Forum "OS X-Developer" wurde erstellt von Wikinator, 22.08.05.

  1. Wikinator

    Wikinator Adams Parmäne

    Dabei seit:
    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?
     
  2. Dadelu

    Dadelu Reinette Coulon

    Dabei seit:
    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 ;)
     
  3. Wikinator

    Wikinator Adams Parmäne

    Dabei seit:
    21.08.04
    Beiträge:
    1.297
    sicher, aber wie schreibe ich eine Zeitzähl-Schleife?
     
  4. Dadelu

    Dadelu Reinette Coulon

    Dabei seit:
    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
     
  5. Thof

    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.
     
  6. Wikinator

    Wikinator Adams Parmäne

    Dabei seit:
    21.08.04
    Beiträge:
    1.297
    danke euch beide, ich werde mir die Links durchlesen und es versuchen. :)
     
  7. Dadelu

    Dadelu Reinette Coulon

    Dabei seit:
    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 ;)
     
  8. Thof

    Thof Gast

    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() { ... }
    
    ;)
     
    Wikinator gefällt das.
  9. Dadelu

    Dadelu Reinette Coulon

    Dabei seit:
    06.07.05
    Beiträge:
    939
    1A Beitrag! Genau so geht die Sache ;)
     
  10. Wikinator

    Wikinator Adams Parmäne

    Dabei seit:
    21.08.04
    Beiträge:
    1.297
    ja, danke für die anschauliche Erklärung :)
     
  11. mullzk

    mullzk Linsenhofener Sämling

    Dabei seit:
    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]
     
  12. Thof

    Thof Gast

    Sehr fein... wieder was gelernt :-D :) :-D
     
  13. Dadelu

    Dadelu Reinette Coulon

    Dabei seit:
    06.07.05
    Beiträge:
    939
    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.. :(
     
  14. commander

    commander Baldwins roter Pepping

    Dabei seit:
    25.02.04
    Beiträge:
    3.210
    @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:

    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
     
    #14 commander, 22.08.05
    Zuletzt bearbeitet: 23.08.05
  15. commander

    commander Baldwins roter Pepping

    Dabei seit:
    25.02.04
    Beiträge:
    3.210
    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, [​IMG] 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
     
  16. mullzk

    mullzk Linsenhofener Sämling

    Dabei seit:
    04.01.04
    Beiträge:
    2.529
    schade, ich lerne immer wieder gerne von leuten, die von java wirklich viel verstehen, und du gehörst definitiv in diese kategorie

    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:
     
  17. commander

    commander Baldwins roter Pepping

    Dabei seit:
    25.02.04
    Beiträge:
    3.210
    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...
     
    #17 commander, 23.08.05
    Zuletzt bearbeitet: 23.08.05
    cws gefällt das.

Diese Seite empfehlen