Code für x Sekunden in Java ausführen?

Ich möchte eine Java While-Schleife schreiben, die 15 Sekunden lang iteriert. Eine Möglichkeit, dies zu tun, wäre, die aktuelle Systemzeit + 15 Sekunden zu speichern und diese dann mit der aktuellen Zeit in der While-Loop-Signatur zu vergleichen.

Gibt es einen besseren Weg?

Das Design hängt davon ab, was Sie für 15s tun möchten. Die zwei plausibelsten Fälle sind: “Mach das alle X für 15s” oder “Warte auf X, oder 15s, je nachdem, was früher eintritt”, was zu einem sehr unterschiedlichen Code führen wird.

Einfach warten

Thread.sleep (15000)

Dies wird nicht iteriert, aber wenn Sie nichts für 15s tun wollen, ist es viel effizienter (es verschwendet weniger CPU beim Nichtstun).

Wiederholen Sie einige Code für 15s

Wenn Sie wirklich für 15s eine Schleife machen wollen, ist Ihre Lösung in Ordnung, solange Ihr Code nicht zu lange dauert. Etwas wie:

long t= System.currentTimeMillis(); long end = t+15000; while(System.currentTimeMillis() < end) { // do something // pause to avoid churning Thread.sleep( xxx ); } 

Warte 15 Sekunden oder eine andere Bedingung

Wenn Sie möchten, dass Ihr Code genau nach 15 Sekunden unterbrochen wird, benötigen Sie eine Multithreading-Lösung. Sehen Sie sich java.util.concurrent für viele nützliche Objekte an. Die meisten Methoden, die sperren (wie wait ()), haben ein Timeout-Argument. Ein Semaphor könnte genau das tun, was Sie brauchen.

Wie bereits von anderen Postern erwähnt, verwenden Sie Thread.sleep() , wenn Sie möchten, dass der Thread für einige Zeit Thread.sleep() .

Wenn Sie möchten, dass der Thread etwas ausführt, aber nach einer Weile anhalten soll, verwenden Sie Folgendes:

 class Foo implements Runnable { private volatile boolean killed = false; public void run() { while (!killed) { try { doOnce(); } catch (InterruptedException ex) { killed = true; } } } public void kill() { killed = true; } private void doOnce() throws InterruptedException { /* .. */ } } 

und aus dem Hauptthread:

 Foo foo = new Foo(); Thread thread = new Thread(foo); thread.start(); /* when you want to stop it */ foo.kill(); thread.interrupt(); 

Versuche dies:

 public class SleepMessages { public static void main(String args[]) throws InterruptedException { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; for (int i = 0; i < importantInfo.length; i++) { //Pause for 15 seconds Thread.sleep(15000); //Print a message System.out.println(importantInfo[i]); } } } 

mehr Infos: hier

Ihr allgemeiner Ansatz scheint gut zu sein, obwohl Sie vielleicht sehen möchten, ob die aktuelle Zeit größer ist als der Punkt, den Sie stoppen möchten, da Sie sonst möglicherweise für eine lange Zeit laufen.

Die Alternative besteht darin, einen Timer / Thread auszuführen, der nach Ablauf von 15 Sekunden ein Flag setzt. Dieses Flag müsste als flüchtig markiert werden, da die Schleife sonst möglicherweise nicht in dem Wert enthalten ist.

Die Wahl, wenn Sie an Effizienz interessiert sind, ist die, die teurer ist, die Systemzeit einmal pro Schleife zu erhalten oder auf eine flüchtige Variable zuzugreifen? Ich weiß nicht, welches effizienter ist – Sie könnten es benchmarken, wenn es wirklich wichtig ist.

Für einfachen, wartbaren Code würde ich den Timer-Check-Ansatz wählen:

 long endTime = System.currentTimeMillis() + 15000 while (System.currentTimeMillis() < endTime) { //loop } 

Sie können AOP und eine @Timeable Annotation von jcabi-aspects (ich bin ein Entwickler) verwenden:

 @Timeable(limit = 1, unit = TimeUnit.SECONDS) String load(String resource) { // do this check regularly: if (Thread.currentThread.isInterrupted()) { throw new IllegalStateException("time out"); } // execution as normal } 

Wenn das Zeitlimit erreicht ist, wird Ihr Thread interrupted() -Flag auf ” true und es ist Ihre Aufgabe, diese Situation korrekt zu behandeln und die Ausführung zu stoppen.

Angenommen, Sie möchten, dass die Schleife etwas Sinnvolles tut, könnten Sie es schneller finden, eine flüchtige Flagge zu überprüfen. Lassen Sie einen anderen Thread 15 Sekunden warten (oder verwenden Sie einen Timer) und stellen Sie ihn dann ein.

Alternativ, wenn Sie ungefähr wissen, wie lange der Schleifenkörper dauern wird, führen Sie ihn einige hundert Male aus und sagen Sie die Zeit in einer äußeren Schleife an.

 final long start = System.nanoTime(); do { for (int i=0; i<200, ++i) { ... } } while (System.nanoTime()-start < 15L*1000L*1000L*1000L); 

System.nanoTime sollte nicht durch Systemtaktänderungen verwirrt werden. Die Verwendung von langen Literalzahlen ist wichtig.

Möglicherweise möchten Sie eine TimerTask einplanen, die einen anderen Thread stoppt oder den Zustand Ihrer Schleife ändert.

Nie auf die aktuelle Zeit in einer engen Schleife prüfen.

Sonst kann jemand mit einem Laptop durch eine überhitzte CPU seine Runde verbrennen lassen. Ich habe die Geschichten darüber gehört.

Weitere Informationen zum java.util.concurrent- Ansatz finden Sie in Kapitel 6 von Java-Parallelität in der Praxis (Abschnitt 6.3.7 Zeitlimits für Tasks festlegen, Seite 131).

Codebeispiel : Abrufen einer Anzeige mit einem Zeitbudget.

Eine Lösung ähnlich @ Tom Hawtin ohne eine willkürliche Schleifengröße.

 final long end = System.nanoTime() + 15 * 1000 * 1000 * 1000L; int loop = 1; do { for (int i=0; i 

In diesem Fall beginnt die Größe der inneren Schleife klein, wird aber größer, wenn die Schleife besonders schnell ist. Wenn es langsam genug ist, wird es möglicherweise nur einmal durchlaufen.

Hier ist mein Vorschlag und es funktioniert gut für mich 🙂

 StoppingTime = 15 ; int loop = 1; long StartTime = System.currentTimeMillis() / 1000 ; for (int i=0; i StoppingTime) loop=0; } 

Ich würde vorschlagen, dass Sie dies mit der Timer-class tun, die das Thread.sleep (xxx) vermeidet; Methode.

beispielsweise:

 import java.util.Timer; import java.util.TimerTask; public class TimerExample { private int globalTimer = 0; private int limitTimer = 15; public static void main(String[] args) { new TimerExample(); } public TimerExample() { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { globalTimer++; // DO YOUR CODE HERE System.out.println("running"); if (globalTimer == limitTimer) { timer.cancel(); } } }, 0, 1000); } }