Java führt den Task mit einer Anzahl von Wiederholungen und einem Timeout aus

8

Ich versuche eine Methode zu erstellen, die eine gegebene Aufgabe in einem maximalen Zeitraum ausführt. Wenn es in dieser Zeit nicht fertig ist, sollte es einige Male wiederholt werden, bevor es aufgibt. Es sollte auch einige Sekunden zwischen jedem Versuch warten. Hier ist, was ich mir ausgedacht habe, und ich würde gerne einige Kritiken zu meiner Herangehensweise haben. Ist das eine einfachere Methode, dies mithilfe von ScheduledExecutorService zu tun? Oder ist meine Art, dies zu tun, ausreichend?

%Vor%     
Hiro2k 01.08.2012, 01:21
quelle

2 Antworten

5

Ich denke, aber es ist meiner Meinung nach, wenn Sie netzwerkbezogene Aufgaben planen, sollten Sie sie nicht wiederholen, sondern sie eventuell parallel ausführen. Ich beschreibe diesen anderen Ansatz später.

In Bezug auf Ihren Code sollten Sie die Aufgabe an einen Executor oder die FutureTask an einen Thread übergeben. Es wird keinen Thread erzeugen oder alleine ausführen. Wenn Sie einen Executor haben (siehe ExecutorService), brauchen Sie nicht einmal eine FutureTask, Sie können sie einfach planen und eine abrufbare Funktion erhalten.

Wenn Sie also einen ExecutorService haben, können Sie Folgendes aufrufen:

%Vor%

Future.get (timeout) wartet auf dieses Zeitlimit und kehrt eventuell mit TimeoutException zurück, auch wenn der Task noch nie gestartet wurde, beispielsweise wenn der Executor bereits mit anderen Aufgaben beschäftigt ist und keinen freien Thread finden kann. Sie könnten also fünf Mal versuchen und Sekunden warten, ohne der Aufgabe eine Chance zum Laufen zu geben. Dies kann oder kann nicht sein, was Sie erwarten, aber normalerweise ist es nicht. Vielleicht solltest du darauf warten, dass es startet, bevor du eine Auszeit gibst.

Außerdem sollten Sie die Zukunft explizit abbrechen, auch wenn sie TimeoutException auslöst, sonst läuft sie möglicherweise weiter, da weder die Dokumentation noch der Code sagt, dass sie aufhören wird, wenn ein get mit Timeout fehlschlägt.

Auch wenn Sie es abbrechen, es sei denn, das Callable wurde "richtig geschrieben", könnte es für einige Zeit weiterlaufen. Nichts, was Sie in diesem Teil des Codes dagegen tun können, denken Sie daran, dass kein Thread "wirklich stoppen" kann, was ein anderer Thread in Java tut, und zwar aus guten Gründen.

Ich nehme jedoch an, dass Ihre Aufgaben hauptsächlich netzwerkbezogen sind, daher sollte es korrekt auf eine Thread-Unterbrechung reagieren.

Ich benutze normalerweise eine andere Strategie ist Situationen wie diese:

  1. Ich würde public static T execute schreiben (Callable task, int maxTries, int timeout), also die Aufgabe, maximale Anzahl der Versuche (potentiell 1), max totaler Timeout ("Ich will eine Antwort in max. 10 Sekunden, egal wie oft du es versuchst, 10 Sekunden oder nichts ")
  2. Ich spawne die Aufgabe, gebe sie einem Executor und rufe dann future.get (timeout / tries)
  3. auf
  4. Wenn ich ein Ergebnis erhalte, gib es zurück. Wenn ich eine Ausnahme erhalte, versuche es erneut (siehe später)
  5. Wenn ich jedoch eine Zeitüberschreitung erhalte, annulliere ich NICHT die Zukunft, sondern speichere sie in einer Liste.
  6. Ich überprüfe, ob zu viel Zeit vergangen ist oder zu viele Wiederholungen. In diesem Fall annulliere ich alle Futures in der Liste und lege die Ausnahme ab, gebe null zurück, was auch immer
  7. Andernfalls fahre ich mit dem Zyklus fort und plane die Aufgabe erneut (parallel zur ersten).
  8. Siehe Punkt 2
  9. Wenn ich kein Ergebnis erhalten habe, überprüfe ich die Zukunft (en) in der Liste, vielleicht hat es eine der zuvor erstellten Aufgaben geschafft.

Vorausgesetzt, dass Ihre Aufgaben mehr als einmal ausgeführt werden können (wie ich vermute, sind sie es, sonst keine Möglichkeit, es erneut zu versuchen), fand ich diese Lösung für das Netzwerk besser.

Angenommen, Ihr Netzwerk ist tatsächlich sehr beschäftigt, fragen Sie nach einer Netzwerkverbindung mit 20 Wiederholungen von je 2 Sekunden. Da Ihr Netzwerk beschäftigt ist, schafft keiner der 20 Versuche die Verbindung in 2 Sekunden. Eine einzelne Ausführung, die 40 Sekunden dauert, kann jedoch Daten verbinden und empfangen. Es ist wie eine Person, die f5 zwanghaft auf einer Seite drückt, wenn das Netz langsam ist, wird es nichts nützen, da der Browser jedes Mal von vorne beginnen muss.

Stattdessen lasse ich die verschiedenen Futures laufen, der erste, der es schafft, die Daten zu bekommen, wird ein Ergebnis zurückgeben und die anderen werden gestoppt. Wenn der erste hängt, wird der zweite funktionieren, oder der dritte vielleicht.

Vergleiche mit einem Browser ist, als würde man einen anderen Tab öffnen und versuchen, die Seite dort zu laden, ohne den ersten zu schließen. Wenn das Netz langsam ist, wird der zweite einige Zeit brauchen, aber nicht den ersten stoppen, der schließlich richtig geladen wird. Wenn stattdessen der erste Tab angehängt wurde, wird der zweite schnell geladen. Was auch immer zuerst geladen wird, wir können die andere Registerkarte schließen.

    
Simone Gianni 01.08.2012, 02:16
quelle
1

Der Thread, für den% code% aufgerufen wird, blockiert so lange. Nicht sicher, ob das für Sie richtig ist. Für diese Art von Aufgaben ist execute am besten. Sie können eine Aufgabe planen und die Zeitplanung festlegen. Werfen Sie einen Blick auf ScheduledThreadPoolExecutor

    
Bhaskar 01.08.2012 06:14
quelle

Tags und Links