Wie debugge ich dies am besten: SingleThreadExecutor führt Task nicht aus..?

sirbender

Top Contributor
Hi,

eigentlich habe ich schon mehrmals versucht das Problem zu debuggen. Mein aktueller Ansatz:

Executors.newSingleThreadExecutor() führt via scheduleWithFixedDelay(...) ein simples Runnable (A) jede 20min aus (druckt eine Nachricht auf die Konsole). Das funktioniert auch ohne Probleme.

Desweiteren führt er mit 2h Zeitverzögerung ein komplexeres Runnable (B) aus und danach alle 24h. Nach 2h wird das Runnable ausgeführt. Das zweite Mal 24h später aber nicht.

Es werden keine Exceptions geworfen. Es scheint von Aussen alles okay, bis auf das, der SingleThreadExecutor nach 24h eben das Runnable (B) nicht ausführt. Runnable (A) aber problemlos alle 20min.

Zwischendrin hatte ich den Rechner einmal im Standby für 8h. Runnble (A) wird aber weiter ausgeführt. Runnable (B) aber eben nicht wie ge-scheduled. Am SinlgeThreadExecutor scheint es zumindest erstmal nicht zu liegen und auch das Standby scheint nicht der Verursacher, oder?
 

sirbender

Top Contributor
Keiner eine Idee? Schon komisch. Wenn wenigstens eine Exception geworfen würde. Kann man irgendwie den SingleThreadExecutor "befragen" was geht? Seinen Schedule einsehen oder sowas? Irgendwie rausfinden warum da nix ausgeführt wird.
 

LimDul

Top Contributor
Kannst du mal den Code zeigen, der das erzeugt?
scheduleWithFixedDelay liefert dir ja ein ScheduledFuture zurück - und das kannst du befragen wie "lange" es noch warten muss. Musst du halt irgendwo hinpacken, wo du drauf zugreifen kannst.
 

sirbender

Top Contributor
Kannst du mal den Code zeigen, der das erzeugt?
scheduleWithFixedDelay liefert dir ja ein ScheduledFuture zurück - und das kannst du befragen wie "lange" es noch warten muss. Musst du halt irgendwo hinpacken, wo du drauf zugreifen kannst.

Der ganze Code ist extrem eingebettet mit zig Libraries. Ich muss mal schauen ob ich ein Minimales Beispiel schreiben kann.

ScheduledFuture<?> future = STE.scheduleWithFixedDelay(SendMail::sendMail, 7200, 3600*24, TimeUnit.SECONDS);

Die ScheduledFuture kann ich befragen?

Ja, ich kann sie wo reinpacken und befragen (per GUI jederzeit)
 

sirbender

Top Contributor

Ich nutze ja "scheduleWithFixedDelay". Sollte also laut JavaDoc alles passen.

"If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor."

Leider sehe ich nirgends, dass irgendwo eine Exception geworfen wird. Kann ich das irgendwie verpassen?
 

Jw456

Top Contributor
Ein einfaches Beispiel hier

Hast du es mal mit einer kürzeren Verzögerung und periode versucht?

Wie woran merkst du das der task nicht gestartet wird. Nur wenn die Email nicht kommt kann es ja auch was anderes sein.

Ohne Code wird es schwierig Hilfe zu geben.
 

Jw456

Top Contributor
Ja. Es ist eine Methode mit der Signatur eine Runnable. Java behandelt sie also gleich. Führt sie einfach aus. Nach 7200 Sekunden wird sie einmal erfolgreich ausgeführt. Aber 3600*24 Sekunden später nicht mehr.
Einen Thread kann man ja auch nur einmal starten. Dann brauchst du ein neues Objekt von dem Thread.
Zeige doch mal wie du das machst.
 

sirbender

Top Contributor
Ich hab jetzt auf Executors.newScheduledThreadPool(1) umgestellt und das Intervall auf 1000 Sekunden. Hat alles ausgeführt für ein paar Stunden. Ob es am neuen Executor liegt - schwer vorzustellen.
 

sirbender

Top Contributor
Einen Thread kann man ja auch nur einmal starten. Dann brauchst du ein neues Objekt von dem Thread.
Zeige doch mal wie du das machst.
Ich liefere nur das Runnable (was wie gesagt nur eine Methode ist, die funktional gleich ist zu einem Runnable). Ich generiere und starte keine Threads. Das macht alles der: ScheduledExecutorService STE = Executors.newScheduledThreadPool(1);

STE.scheduleWithFixedDelay(...);
 

Jw456

Top Contributor
Ich drucke vor und nach dem Senden der Email auf die Konsole eine Meldung aus. Das Runnable (also die Methode) wird nie ausgeführt.
Dann zeige das doch mal wie du das Runnable erstellst und startest in der sendMail Methode.


Übrigens zu deinen ersten Post.
Executors.newSingleThreadExecutor() führt via scheduleWithFixedDelay(...)
newSingleThreadExecutor() kann nicht die Methode scheduleWithFixedDelay(...) aus Führen.
Das hätte dir deine DIE auch sagen müssen. Deine Angaben an uns können so nicht ganz stimmen.

Deshalb auch immer die Frage wie du am Anfang deine Variable „STE“ erstellt hast. Das bist du uns bis jetzt immer noch schuldig geblieben.
 

mrBrown

Super-Moderator
Mitarbeiter
Jw456 Nur ein nett gemeinter Rat: wenn du von einem Thema wenig Ahnung hast, was hier sehr offensichtlich der Fall ist, ist keine Hilfe manchem besser als falsche Hilfe. Von deinen 9 Beiträgen ist hier tatsächlich keiner wirklich hilfreich, und z.T. auch einfach falsch.
 

KonradN

Super-Moderator
Mitarbeiter
Hoffe, da hijacke ich den Thread jetzt nicht. Wenn es um Libraries und so geht, dann würde mir hier teilweise AOP einfallen und dann kommt direkt die Frage:

Arbeitet jemand mit AOP?

Wenn es nur darum geht, dass man Exceptions generell loggen möchte, dann wäre das ja eigentlich ein typisches Beispiel für einen Aspekt und der kann dann auch relativ einfach geschrieben werden (z.B. mit AspectJ):

Java:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class ExceptionLoggingAspect {

    @Pointcut("within(com.my.project..*)")
    public void myPointcut() {}

    @AfterThrowing(pointcut = "myPointcut()", throwing = "ex")
    public void logException(JoinPoint joinPoint, Throwable ex) {
        System.out.println("Exception in " + joinPoint.getSignature() + ": " + ex.getMessage());
    }
}

Der Aspect würde jetzt bei allen Methoden in dem Package com.my.project angewendet und wenn eine Exception geworfen wird, dann wird auch das logException aufgerufen.

Natürlich kann man sowas objektorientiert bauen und ich sehe nicht wirklich einen Grund, dass man da nicht ein einfaches try / catch verwendet wenn man irgendwas auf einem anderen Thread macht. Und wenn man davon mehrere Sachen hat, dann vererbt man das eher....

Der Thread ist also nicht wirklich als Lösungsidee für die Problematik des TE gedacht, denn ich würde in einem Projekt deshalb nicht AspectJ einbinden.
 

sirbender

Top Contributor
Wenn im Runnable Exceptions geworfen werden, werden diese "verschluckt". Am sinnvollsten wird es sein, den ganzen Code in sendMail in try-catch zu wrappen und dort jede Exception zu loggen.
So war das Runnable immer schon - kompletter try-catch samt Logging um den Code. Nur schlägt das Logging nie an.

Zwischendrin hatte ich den Rechner einmal im Standby für 8h.

Ich glaube ich weiss jetzt woran es liegt. Ich habe es ja wöchentliche Ausführung eingestellt. D.h. nach 24*3600*7 Sekunden. Nur wird der Rechner jede Nacht in Standby versetzt. Jetzt hatte ich angenommen, dass intern einfach die Standby-Zeit mitgerechnet wird. Meine Theorie ist, dass dies nicht so ist. D.h. über eine Woche ist ca. 7 * 8 Stunden (eher sogar mehr) Standby. Das sind mehr als 2 Tage. Ich wartete viele Stunden und nichts passierte...scheinbar hätte ich länger warten müssen wegen dem Standby.

Ich muss noch ein paar Tests machen, aber ich glaube das war mein Problem. Sehr dämlich :(

Ich glaube ich mache es jetzt so, dass ich das Runnable öfter ausführe (jede Stunde) und den Code im Runnable dann selbst entscheiden lasse ob das Senden einer Email gerade Sinn macht.
 

Oneixee5

Top Contributor
Warum verwendest du nicht einfach Cron oder den Task Scheduler? Wenn das Programm alle 24h ausgeführt werden soll, dann muss es doch gar nicht die ganze Zeit laufen. Das verschwendet nur Ressourcen. Es wäre auch möglich den Task zu wiederholen wenn der Rechner zur eigentlichen Zeit aus war, zumindest unter Linux.
 
Zuletzt bearbeitet:

sirbender

Top Contributor
Warum verwendest du nicht einfach Cron oder den Task Scheduler? Wenn das Programm alle 24h ausgeführt werden soll, dann muss es doch gar nicht die ganze Zeit laufen. Das verschwendet nur Ressourcen. Es wäre auch möglich den Task zu wiederholen wenn der Rechner zur eigentlichen Zeit aus war, zumindest unter Linux.
Verbraucht das soviele Resourcen wenn es hauptsächlich schläft, oder ist das in Java "teuer" implementiert?

Ich hatte Cron in der Tat in Erwägung gezogen und schon ein bischen gelesen. Insgesamt hatte ich halt gedacht, dass bei 100% Java weniger Moving Parts sind, es platformunabhängig ist und ich generell mehr Kontrolle habe. Ich denke es gibt wohl auch Cron-Libraries für Java, die genauso funktionieren wie Cron - aber die sind dann bestimmt auch nicht resourcenschonender.

Wenn im Runnable Exceptions geworfen werden, werden diese "verschluckt". Am sinnvollsten wird es sein, den ganzen Code in sendMail in try-catch zu wrappen und dort jede Exception zu loggen.

Ich habe gerade mal meine Methode, die ich als Runnable nutze ohne try-catch geschrieben - also mit "throws" in der Signatur, aber die IDE lässt mich das so nicht an scheduleWithFixedDelay(...) übergeben. Er meckert, dass die Exception nicht gehandelt wird und schlägt try/catch vor. Wie schaffe ich es denn dann überhaupt, dass eine Exception verschluckt wird?
 

KonradN

Super-Moderator
Mitarbeiter
Verbraucht das soviele Resourcen wenn es hauptsächlich schläft, oder ist das in Java "teuer" implementiert?
Das spielt alles absolut keine Rolle. Klar, hast du da beim Start dann eine ganze JavaVM, die gestartet wird und dann durchläuft, aber das ist ja ein einmaliger Aufwand. Danach wird das System Speicherseiten auslagern können, so es Probleme mit dem Speicher gibt, aber das wird in der Regel kein Problem sein und nur interessant, wenn das System komplett unterdimensioniert ist oder Du den Speicher durch andere Dinge verbraucht hast. (Dann gilt aber wie immer der Ansatz, dass man das analysiert und prüft, wo der Speicher eigentlich geblieben ist!)

Und was wir hier komplett aussen vor gelassen haben und noch gar nicht betrachtet haben, sind die Anforderungen.
  • Wenn Du eh schon eine Java Anwendung durchlaufen hast: Natürlich nehme ich die dann alleine schon, um die Installation / Administration zu vereinfachen. Das ist deutlich einfacher als dann cron und co für alle möglichen Betriebssysteme zu erläutern. Willst Du cron auf einem Mac nutzen? Geht, aber in meinen Augen hat das gleich einen negativen Touch, denn der Mac nutzt eigentlich den LaunchDaemon. Also viel Spass, alles für Unix, Mac, Windows, ... zu beschreiben ... Man merkt: Das ist mehr Aufwand, als da einen kleinen Scheduler in der eigenen Anwendung zu integrieren..
  • Was auch ein Punkt sein kann: Was für Expertisen sind schon da? Was willst Du in Produktion auf cron setzen, wenn du Dich damit ganz offensichtlich nicht auskennst? Ja klar, kann man alles lernen. Aber was willst Du alles können? Linux, Mac, Windows, Cloud Umgebungen, .... Wird schnell viel zu viel :)
  • Um etwas mit cron starten zu können, darfst Du dann ein Kommandozeilen-Interface unterstützen. Das ist ggf. schon mehr Aufwand, als unbedingt notwendig.

Also nicht falsch verstehen: Die Idee, cron einzusetzen, ist durchaus legitim. Aber man muss die Anforderungen analysieren um zu schauen, was man wirklich braucht und dann kann man Vor- und Nachteile abwägen (Die Liste ist nur, was mir spontan in den Kopf gekommen ist).

Ich habe gerade mal meine Methode, die ich als Runnable nutze ohne try-catch geschrieben - also mit "throws" in der Signatur, aber die IDE lässt mich das so nicht an scheduleWithFixedDelay(...) übergeben. Er meckert, dass die Exception nicht gehandelt wird und schlägt try/catch vor. Wie schaffe ich es denn dann überhaupt, dass eine Exception verschluckt wird?
Ich weiss jetzt gerade nicht, was hier das genaue Problem ist. Daher einfach einmal ein paar Grundlagen:

Wenn eine Exception geworfen wird, dann wird diese den StackTrace hoch gereicht, bis die Exception behandelt wird oder die Exception sozusagen in der JVM ankommt. Wenn letzteres passiert, dann kann die JVM nur den entsprechenden Handlungsstrang beenden.

Wenn Du einen neuen Thread startest, dann hast Du da eine Ausführung mit einem eigenen, neuen StackTrace. Die oberste Ebene ist dann unter dem Strich das run(). Wenn Du da Exceptions nicht behandelst, dann wird die Exception nicht behandelt und der Thread wird beendet.

Das, worüber du jetzt gerade stolperst: Es gibt checked und unchecked (Runtime) Exceptions. Wenn eine checked Exception in einer Methode geworfen werden kann, dann muss dies in der Signatur vermerkt sein und der Aufrufer muss diese Exception entweder fangen oder selbst auch diese Exception werfen.

Wenn Du Methoden überschreibst, dann kannst Du keine neuen checked Exceptions hinzu nehmen (JLS 8.4.8.3) Das wird vermutlich die Problematik erläutern, dass eine Methode mit checked Exception nicht erlaubt ist bei einem funktionalen Interface mit einer Methode ohne checked Exception. Aber das ist jetzt alles geraten, da Du uns die Problematik nicht wirklich beschrieben hast.

Was Dir das hier versucht wurde zu sagen: Du solltest an allen Stellen, an denen Du einen neuen StackTrace bekommst, Exceptions fangen und loggen. Das kann durch ein einfaches try/catch sein, wo Du den Aufruf hast. Oder Du kannst eine Hilfsklasse bauen - etwas wie:
Java:
public class ExceptionLoggingRunnableFactory {

    public static Runnable create(final Runnable runnable) {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } catch (Exception ex) {
                    System.err.println("Exception in Runnable: " + ex.getMessage());
                    ex.printStackTrace(System.err);
                }
            }
        };
    }
}

Oder als Interface evtl. etwas wie
Java:
public interface ExceptionLoggingRunnable extends Runnable {

    default void run() {
        try {
            loggedRun();
        } catch (Exception ex) {
            System.err.println("Exception in Runnable: " + ex.getMessage());
            ex.printStackTrace(System.err);
        }

    }
    
    void loggedRun();
}

Oder irgendwie sowas ... ich habe mir da jetzt nicht wirklich einen Kopf über ein Design gemacht und einfach mal schnell die zwei Ideen gebracht, die mir so in den Sinn gekommen sind. Aber ich bezweifle auch etwas den Sinn. Da macht evtl. eher ein Aspekt Sinn, so man AOP schon nutzt (z.B. Spring Framework nutzt AOP).

Aber so ein try / catch wie in den Lösungen gezeigt, sind ja nun wirklich nichts komplexes und können problemlos hinzugenommen werden ohne dass der Code unleserlich wird. Ich bin auch gewohnt, ein gewisses Logging zu verwenden. Da wäre dann etwas wie:
Java:
try {
    log.info("Cool Thread started ...");
    // Do whatever you want here
} catch (Exception ex) {
    log.error("Unhandled Exception thrown in Cool Thread.", ex);
} finally {
    log.info("Cool Thread ended ...");
}
mit "Cool Thread" natürlich der Angabe, was das für ein Thread ist...
 

Oneixee5

Top Contributor
Ich denke die Weitergabe und Plattformunabhängigkeit wird eine untergeordnete Rolle spielen. Welcher Normalnutzer lässt schon 24/7 seinen Rechner laufen, damit ein Job ausgeführt wird. Außerdem wäre dann auch Autostart zu implementieren. Für Cron etc. gibt es GUI-Tools, falls die Lernkurve zu steil wäre. Auch ohne diese gibt es 100e Webseiten zur Erstellung und Prüfung von Cron-Expressions. Da muss muss man auch nicht viel lesen - auf jeden Fall weniger als dafür, in Java Threads richtig und fehlerfrei zu implementieren.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Gibt es irgendeine Möglichkeit, dies zu tun?(Android Studio) Java Basics - Anfänger-Themen 1
S Ist dies ein Bug in Eclipse Java Basics - Anfänger-Themen 2
JavaNewbie2.0 Warum ist dies nicht möglich? Java Basics - Anfänger-Themen 7
O Starte Timer, während anderer Timer noch läuft. Ruft dies Schwierigkeiten hervor? Java Basics - Anfänger-Themen 0
O Funktioniert dies? Und gibt es eine bessere Lösung? Java Basics - Anfänger-Themen 6
Chocola Datums-String mit "ungültigem Anhängsel" wird ohne Fehler geparsed. Kann man dies irgendwie beheben? Java Basics - Anfänger-Themen 3
Z Array mit daten einer datenbankbefüllen und dies an eine tabelle geben Java Basics - Anfänger-Themen 6
P Keinen Wert - wie kann dies in eine Bedinung geprüft werden Java Basics - Anfänger-Themen 4
T aktuelles jahr ermitteln (und nur dies) Java Basics - Anfänger-Themen 3
C Sollte man dies kapseln? Java Basics - Anfänger-Themen 4
D Kann dies Java? Java Basics - Anfänger-Themen 29
D Datentypen Wie am Besten abspeichern Java Basics - Anfänger-Themen 1
julian-fr Wie kann ich am besten Java lernen? Java Basics - Anfänger-Themen 17
belana wie am besten 2D Array von String to Integer Java Basics - Anfänger-Themen 18
Salvatore321 Wie kann ich dieses Zustandsdiagramm am besten Umsetzen? Java Basics - Anfänger-Themen 5
dieter000 Hilfe bei dem Beispiel, wie gehe ich sowas am besten an? Java Basics - Anfänger-Themen 32
M konzeptuelle Frage: In welcher Klasse definiert man am Besten Methoden, die die Kommunikation mit dem User regeln? Java Basics - Anfänger-Themen 8
I Wo am besten eine String Konstante initialisieren? Java Basics - Anfänger-Themen 5
A Wie sollte ich es am besten an gehen - denkweise Java Basics - Anfänger-Themen 48
E Erste Schritte Java Webeintwicklung (JSP/Servlet), wie am Besten einsteigen? Java Basics - Anfänger-Themen 0
V welche Methode am besten sich für JPG einfügung in Java anzugewöhnen ? Java Basics - Anfänger-Themen 4
I Grafische Benutzeroberflächen - welche Komponente nehme ich am besten? Java Basics - Anfänger-Themen 13
DStrohma Best Practice Wie setze ich Suchparameter am besten? Java Basics - Anfänger-Themen 3
J Wie handle ich Threads am besten? Java Basics - Anfänger-Themen 2
H Wo speichert man am besten Daten? Appdata? Java Basics - Anfänger-Themen 14
B Datentypen Wie Daten am besten organisieren? Java Basics - Anfänger-Themen 7
M wie kann ich am besten die kleinste 2 elemente von einer Liste kriegen Java Basics - Anfänger-Themen 4
S Wie kann man am besten programmieren erlernen? Java Basics - Anfänger-Themen 32
P OOP Wie schreib ich dieses Programm am besten? Java Basics - Anfänger-Themen 6
B Wie lerne ich am besten? Java Basics - Anfänger-Themen 7
C Wie am besten die Verarbeitung der Eingabe verzögern ? Java Basics - Anfänger-Themen 5
C Wie Objekte am besten anklickbar machen ? Java Basics - Anfänger-Themen 9
H Wie lerne ich am Besten Java Java Basics - Anfänger-Themen 28
K OPP am besten verstehen !!! Java Basics - Anfänger-Themen 7
S Wie ereuge ich hier am besten eine Schleife Java Basics - Anfänger-Themen 12
D Logging sätmlicher Vorgänge, wie am besten realisieren? Java Basics - Anfänger-Themen 6
A wie lernt man am besten den code zu verstehen? Java Basics - Anfänger-Themen 7
G wo speichert man am besten eine Datei? Java Basics - Anfänger-Themen 4
A Welches GUI nutze ich am Besten? Java Basics - Anfänger-Themen 7
B mit was am besten speichern und abrufen?+ fenster in fenster Java Basics - Anfänger-Themen 4
G Massenersetzungen am besten auch mit replaceAll? Java Basics - Anfänger-Themen 3
F Anfänger - die besten Tipps Java Basics - Anfänger-Themen 3
G Wann am besten getSize() aufrufen? Java Basics - Anfänger-Themen 6
S Wie am besten JAVA lernen Java Basics - Anfänger-Themen 12
D Fehlerbehandlungen, wie am besten sinnvoll einsetzen? Java Basics - Anfänger-Themen 6
S schwieriger String für StringTokenizer, wie am Besten ? Java Basics - Anfänger-Themen 8
frau-u guter Stil - wie macht mans am Besten? Java Basics - Anfänger-Themen 8
A Wie fange ich am besten mit nem Programm an? Java Basics - Anfänger-Themen 10

Ähnliche Java Themen

Neue Themen


Oben