[Java] Timer - ScheduledExecutorService?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

Soweit ich es verstehe, soll der Timer nur eine einmalige Zeit abwarten. Also würde ich auch eine passendere Methode dafür verwenden.

var delay = (TIME_DAYS * 86400000) + (TIME_HOURS * 3600000) + (TIME_MINUTES * 60000) + (TIME_SECONDS * 1000);
timer.schedule(() => new Stop(), delay, TimeUnit.MILLISECONDS);

Da nicht bei jedem ActionEvent ein neuer Threadpool gestartet werden sollte (du benötigst insgesamt nur einen einzigen), sollte der Scheduler besser als Feld der Klasse deklariert werden.

private final ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);

Wenn nach diesen Änderungen das Problem noch immer auftritt, solltest du einmal folgende Punkte prüfen:

  • Das tatsächliche Ergebnis in delay im Fehlerfall.
  • Ob der Stop-Konstruktor eine Exception auslöst.
verreisterNutzer  29.08.2022, 17:46

Scheint bisher besser zu laufen.

Kurz etwas anderes:

Macht es eigentlich immer Sinn, ein Thread-Objekt woanders zu deklarieren, um woanders darauf zuzugreifen? Denn ScheduledExecutorService ist ja jetzt auch ein Objekt, auf das in der ganzen Klasse zugegriffen werden kann.

Angenommen:

// Main.java (instance):
public Thread threadA;
public Thread threadB;

public void startThreadA() {
 threadA.start();
}

@Deprecated
public void stopThreadA() {
 threadA.stop();
}

// The same for B...


// KlasseA.java:
main.threadA = new Thread(() -> {
// do things I like...
});
main.startThreadA();

// ...
0
regex9  30.08.2022, 12:12
@verreisterNutzer

Für eine äußere Einflussnahme oder um Objekte, die du wiederverwenden möchtest, brauchst du auf jeden Fall eine Referenz. Wiederverwendbarkeit ist gerade bezüglich des Ressourcenverbrauchs ein wichtiges Thema.

Wenn man beispielsweise mehrere Threads braucht, ist es günstig, einen Threadpool zu nutzen, der deren Verwaltung übernimmt (er merkt sich dafür intern die Threadreferenzen). Von so einem Pool braucht man wiederum nur einen. Getreu dem Motto: Mehrere Köche verderben den Brei.

1
verreisterNutzer  30.08.2022, 23:02
@regex9

Ich habe mir ThreadPools mal angeschaut und so wie ich es aufgefunden habe, wird erst ein Thread nach dem Beenden des vorherigen Threads gestartet. Hier

Oder sind ThreadPools so anzuwenden, dass mehrere Threads in unterschiedlichen Klassen gleichzeitig laufen?

Wie sieht es mit ThreadPools überhaupt in dieser Beispielanwendung aus?:

main.threadA = new Thread(() -> {
function();
});
main.startThreadA();

void function() {
main.threadB = new Thread(() -> {
// do
});
main.startThreadB();
}

ThreadPools scheinen aber, wie ich sie bis jetzt verstanden habe, sehr nützlich zu sein.

0
regex9  31.08.2022, 14:14
@verreisterNutzer

Der Threadpool nimmt mehrere Aufgaben an und die verteilt er dann auf verschiedene Threads. Diese laufen parallel.

Hinsichtlich des Poolverhaltens gibt es verschiedene Typen (die von den Executor-Klassen in Java implementiert werden). Ein Fixed Threadpool beispielsweise besitzt eine bestimmte Anzahl an Threads, die immer verfügbar sind (selbst wenn sie gerade nichts tun). Das sind die Kernthreads, deren Anzahl über die corePoolSize gesteuert wird.

Executors.newScheduledThreadPool(5); // pool with 5 core threads

Zusätzlich kann der Threadpool weitere Threads anlegen, wenn gerade alle Kernthreads belegt sind. Diese Threads werden beendet, sobald sie ihre Aufgabe erfüllt haben. Um den Pool einzugrenzen, kann man eine maximale Anzahl an Threads festlegen, die zur gleichen Zeit im Pool liegen dürfen.

Eine Lösung für zwei Tasks könnte so aussehen:

var executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
executor.submit(() -> { /* Do something */ });
executor.submit(() -> { /* Do something else */ });

Ein Cached Threadpool wiederum kann uneingeschränkt wachsen. Es gibt dafür aber keine Kernthreads. Inaktive Threads werden nach einer bestimmten Wartezeit beendet.

1