Gibt es eine gute Standardmethode, um eine Blockierungsmethode mit einem Timeout in Java aufzurufen? Ich möchte in der Lage sein:
// call something.blockingMethod();
// if it hasn't come back within 2 seconds, forget it
wenn das Sinn macht.
Vielen Dank.
java
concurrency
jjujuma
quelle
quelle
Antworten:
Sie könnten einen Executor verwenden:
Wenn das
future.get
nicht in 5 Sekunden zurückkehrt, wirft es aTimeoutException
. Das Zeitlimit kann in Sekunden, Minuten, Millisekunden oder einer beliebigen Einheit konfiguriert werden, die als Konstante in verfügbar istTimeUnit
.Weitere Informationen finden Sie im JavaDoc .
quelle
BlockingMethodCallable
deren Konstruktor die Parameter akzeptiert, an die Sie übergeben möchten,blockingMethod()
und speichern Sie sie als Mitgliedsvariablen (wahrscheinlich als endgültig). Danncall()
übergeben Sie diese Parameter an dieblockMethod()
.future.cancel(true)
- Die Methode cancel (boolean) im Typ Future <Object> gilt nicht für die Argumente ()Sie können den Aufruf in a
FutureTask
einschließen und die Timeout-Version von get () verwenden.Siehe http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/FutureTask.html
quelle
Siehe auch Guavas TimeLimiter, der einen Executor hinter den Kulissen verwendet.
quelle
Dafür gibt es auch eine AspectJ-Lösung mit der jcabi-aspekte- Bibliothek.
Es kann nicht prägnanter werden, aber Sie müssen sich natürlich auf AspectJ verlassen und es in Ihren Build-Lebenszyklus einführen.
Es gibt einen Artikel, der dies weiter erklärt: Begrenzen Sie die Ausführungszeit der Java-Methode
quelle
Es ist wirklich großartig, dass die Leute versuchen, dies auf so viele Arten umzusetzen. Aber die Wahrheit ist, es gibt keinen Weg.
Die meisten Entwickler würden versuchen, den Blockierungsaufruf in einen anderen Thread zu stellen und eine Zukunft oder einen Timer zu haben. ABER es gibt in Java keine Möglichkeit, einen Thread extern zu stoppen, geschweige denn einige sehr spezifische Fälle wie die Methoden Thread.sleep () und Lock.lockInterruptibly (), die die Thread-Unterbrechung explizit behandeln.
Sie haben also wirklich nur 3 generische Optionen:
Setzen Sie Ihren Blockierungsaufruf auf einen neuen Thread. Wenn die Zeit abgelaufen ist, fahren Sie einfach fort und lassen diesen Thread hängen. In diesem Fall sollten Sie sicherstellen, dass der Thread als Daemon-Thread festgelegt ist. Auf diese Weise verhindert der Thread nicht, dass Ihre Anwendung beendet wird.
Verwenden Sie nicht blockierende Java-APIs. Verwenden Sie beispielsweise für das Netzwerk NIO2 und die nicht blockierenden Methoden. Verwenden Sie zum Lesen von der Konsole Scanner.hasNext (), bevor Sie blockieren usw.
Wenn Ihr blockierender Aufruf kein E / A ist, sondern Ihre Logik, können Sie wiederholt prüfen
Thread.isInterrupted()
, ob er extern unterbrochen wurde, und einen weiteren Thread-Aufrufthread.interrupt()
für den blockierenden Thread durchführenDieser Kurs über Parallelität https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
geht wirklich durch diese Grundlagen, wenn Sie wirklich verstehen wollen, wie es in Java funktioniert. In einer der Vorlesungen wird tatsächlich über diese spezifischen Einschränkungen und Szenarien gesprochen und wie man sie angeht.
Ich persönlich versuche zu programmieren, ohne so viele Anrufe wie möglich zu blockieren. Es gibt Toolkits wie Vert.x, die es wirklich einfach und performant machen, E / A- und keine E / A-Operationen asynchron und nicht blockierend auszuführen.
Ich hoffe, es hilft
quelle
Beachten Sie, dass stop veraltet ist. Eine bessere Alternative besteht darin, ein flüchtiges boolesches Flag zu setzen. Überprüfen Sie es in blockingMethod () und beenden Sie es wie folgt:
quelle
Versuche dies. Einfachere Lösung. Garantiert, dass der Block nicht innerhalb des Zeitlimits ausgeführt wurde. Der Prozess wird beendet und eine Ausnahme ausgelöst.
Beispiel:
quelle
Ich gebe Ihnen hier den vollständigen Code. Anstelle der von mir aufgerufenen Methode können Sie Ihre Methode verwenden:
quelle
Angenommen, Sie
blockingMethod
schlafen nur ein paar Millis:Meine Lösung ist zu verwenden
wait()
undsynchronized
wie folgt :Also kannst du ersetzen
something.blockingMethod(input)
zu
something.blockingMethod(input, 2000)
Ich hoffe es hilft.
quelle
Sie benötigen eine Leistungsschalterimplementierung wie die im ausfallsicheren Projekt auf GitHub vorhandene.
quelle