2012-10-29 8 views
9

Ich versuche, eine Codezeile jede Sekunde mithilfe von System.currentTimeMillis(); auszuführen.Ausführen von Code jede Sekunde mithilfe von System.currentTimeMillis()

Der Code:

 while(true){ 
      long var = System.currentTimeMillis()/1000; 
      double var2 = var %2; 

      if(var2 == 1.0){ 

       //code to run 

      }//If(): 

     }//While 

Der Code, den ich laufen soll, läuft mehrmals, weil var2 bis 1,0 mehrfach wegen der unendlichen ganzen Schleife gesetzt. Ich möchte nur die Codezeile ausführen, wenn var2 zuerst auf 1.0 festgelegt wird, und dann jedes Mal erneut, wenn var2 1.0 nach 0.0 wird.

+1

Ich sollte wirklich beginnen, Kommentare zu Schleifen und Entscheidungen wie Sie haben. Gut gemacht dafür. – Andy

+1

@Andy - bitte schreibe keine Kommentare zum Schließen solcher Klammern.Verwenden Sie die "show matching brackets" Ihrer IDE und/oder refaktorieren Sie den Code so, dass Sie keine Blöcke haben, die so lang sind, dass Sie * dazu * brauchen. –

+0

@StephenC, ich denke, Andy war sarkastisch. Sein Kommentar war dem OP nicht allzu hilfreich. –

Antwort

14

Wenn Sie auf die Sekunden warten möchten, um zu ändern, können Sie Folgendes verwenden.

long lastSec = 0; 
while(true){ 
    long sec = System.currentTimeMillis()/1000; 
    if (sec != lastSec) { 
     //code to run 
     lastSec = sec; 
    }//If(): 
}//While 

Ein effizienterer Ansatz ist es, bis zur nächsten Sekunde zu schlafen.

while(true) { 
    long millis = System.currentTimeMillis(); 
    //code to run 
    Thread.sleep(1000 - millis % 1000); 
}//While 

Eine Alternative ist ein ScheduledExecutorService

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); 

ses.scheduleAtFixedRate(new Runnable() { 
    @Override 
    public void run() { 
     // code to run 
    } 
}, 0, 1, TimeUnit.SECONDS); 

// when finished 
ses.shutdown(); 

Der Vorteil dieses Ansatzes zu nutzen ist, dass

  • Sie den gleichen Thread teilen eine Reihe von Aufgaben mit unterschiedlichen Perioden haben können.
  • Sie können nicht wiederholende Verzögerung oder asynchrone Aufgaben haben.
  • können Sie die Ergebnisse in einem anderen Thread sammeln.
  • können Sie den Thread-Pool mit einem Befehl herunterfahren.
+0

Danke Ich habe die erste Option verwendet, die Sie – Human

+0

+1 für den ScheduledExecutorService gegeben. – Twinone

2

Sie sollten java.util.Timer und java.util.TimerTask Klasse verwenden.

+2

Wenn Code nicht in UI-Thread (aus offensichtlichen Gründen) ist, kann er auch Thread.sleep – Igor

+2

Die Legacy-Timer und Timer-Task-APIs sind schrecklich. Es gibt keine vernünftige Ausnahmebehandlung und sobald eine Ausnahme auftritt, wird der gesamte Timer-Thread beendet. Sie müssten es erneut ausführen. Es reagiert auch empfindlich auf Änderungen der Systemuhr, Sie müssten die Systemuhr deaktivieren (und die Sommerzeit ausschalten!). Die moderne Java-Util-Concurrent-Service-API hat diese besonderen Probleme nicht. – BalusC

1

Mit Thread.sleep(); wäre perfekt für Ihren Fall.

while(true) 
{ 
    Thread.sleep(1000); // Waiting before run. 
    // Actual work goes here. 
} 
+0

Dies wird nicht jede Sekunde ausgeführt. Dies wartet eine Sekunde nach der Fertigstellung. Der Lauf selbst dauert nicht notwendigerweise 0 Sekunden. Stellen Sie sich vor, dass der Lauf 200ms dauert, dann hätte er eigentlich 800ms warten sollen. Verwenden Sie stattdessen den java-util-Concurrent-Executor-Service. – BalusC

+0

danke, aber ich möchte nicht die Java-Hauptklasse jede Sekunde anhalten. Irgendeine Art, es mit System.currentTimemillis zu tun? – Human

+0

@BalusC Sie haben Recht. Aber diese Antwort dient nur dazu, dem OP einen Tipp zu geben. Er sollte die Schlafzeit konfigurieren. – Juvanis

3

Ich würde die Java executor Bibliotheken verwenden. Sie können eine ScheduledPool erstellen, die runnable und für einen beliebigen Zeitraum ausgeführt werden kann. Zum Beispiel

Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new MyRunnable(), 0, 5, TimeUnit.SECONDS); 

Die MyRunnable-Klasse wird alle 5 Sekunden ausgeführt. MyRunnable muss Runnable implementieren. Das Problem dabei ist, dass es (effizient) jedes Mal einen neuen Thread erstellt, der wünschenswert ist oder auch nicht.

+0

Nicht nur einen neuen Thread erstellen, sondern einen neuen Thread-Pool von 1. – Nick

1

bevorzugte Art und Weise:

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 

passieren dann in Runnables wie:

scheduler.scheduleWithFixedDelay(myRunnable, initDelay, delay, TimeUnit.MILLISECONDS); 

Ich würde den Timer nicht verwenden. Scheduler sind gebaut, um Probleme zu behandeln, die Timer verursachen können. Außerdem ist das Thread.sleep gut für ein einfaches Programm, das Sie schnell für Proof-of-Concept-Dinge schreiben, aber ich würde es nicht in der Unternehmenswelt verwenden.

Verwandte Themen