Ich habe mehrere Callables, die für einige JMX Bohnen fragen, so dass jeder eine Auszeit nehmen darf. Ich möchte nach Werten abstimmen, sagen wir jede Sekunde. Der naivste Ansatz wäre, jeden in einem separaten Thread zu starten, aber ich möchte die Anzahl der Threads minimieren. Welche Optionen muss ich besser machen?Was ist der beste Ansatz zur Planung von Callables, die in einer Umfragesituation eine Zeitüberschreitung haben könnten?
Antwort
Meine Interpretation ist, dass Sie eine Reihe von Callable-Objekten haben, die in einigen Abständen abgefragt werden müssen. Das Problem, wenn Sie einen Thread-Pool verwenden, ist, dass der Pool mit den langsamsten Mitgliedern kontaminiert wird und Ihre schnelleren Mitglieder ausgehungert werden.
Es klingt, als hätten Sie die Kontrolle über die Planung, also könnten Sie einen exponentiellen Backoff-Ansatz in Betracht ziehen. Das heißt, nachdem Callable X ausgeführt wurde (und möglicherweise abgelaufen ist), warten Sie 2 Sekunden statt 1 Sekunde, bevor Sie es neu planen. Wenn es immer noch fehlschlägt, gehen Sie zu 4s, dann 8s usw. Wenn Sie eine ScheduledThreadPoolExecutor verwenden, kommt es mit einer eingebauten Möglichkeit, dies zu tun, so dass Sie Ihre Ausführungen nach einer festgelegten Verzögerung planen können.
Wenn Sie eine konstante Zeitüberschreitung festlegen, reduziert diese Strategie die Anfälligkeit Ihres Pools für die Monopolisierung durch die langsamen. Es ist sehr schwierig, dieses Problem vollständig zu beseitigen. Die Verwendung eines separaten Threads pro abgefragtem Objekt ist wirklich die einzige Möglichkeit, sicherzustellen, dass Sie nicht hungern, und das kann sehr ressourcenintensiv sein, wie Sie sagen.
Eine andere Strategie besteht darin, Ihren Pool in einen schnellen und einen langsamen zu poolen. Wenn ein Objekt ein Zeitlimit erreicht (sagen wir mehr als N-mal), verschieben Sie es in den langsamen Pool. Das hält Ihren schnellen Pool schnell, und während die langsamen sich gegenseitig in die Quere kommen, verstopfen sie zumindest den schnellen Pool nicht. Wenn sie eine Zeit lang gute Statistiken haben, können Sie sie erneut zum schnellen Pool befördern.
Sobald Sie submit
ein Callable
erhalten Sie eine Future
- ein Griff zum zukünftigen Ergebnis. Sie können entscheiden, für dessen Abschluss für eine bestimmte Zeit warten:
Future<String> future = executorService.submit(callable);
try {
future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
} catch ...
Aufruf erhalten mit einem Timeout können Sie eine Ausnahme erhalten, wenn die Aufgabe noch nicht abgeschlossen ist. Dies unterscheidet nicht zwischen nicht gestarteten und gestarteten, aber nicht abgeschlossenen Aufgaben. Auf der anderen Seite wird cancel
einen booleschen Parameter mayStopIfRunning
nehmen, so dass Sie z. Stornieren Sie nur Aufgaben, die noch nicht geplant sind.
i mit robbotic zustimmen ... Implementierung eines ‚cachedThreadPool‘ wird Ihr Problem lösen, da es die Anzahl der Threads auf das optimale Niveau zur gleichen Zeit hat Timeouts beschränken, die Ihre un-genutzten Ressourcen frei werden