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?
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.
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.
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.
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.
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?
Java NewSingleThreadExecutor - Learn about Java's NewSingleThreadExecutor, a powerful tool for managing single-threaded tasks efficiently in concurrent programming.
www.tutorialspoint.com
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.
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.
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.
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);
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.
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.
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.
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):
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.
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 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.
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.
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?
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:
publicclassExceptionLoggingRunnableFactory{publicstaticRunnablecreate(finalRunnable runnable){returnnewRunnable(){@Overridepublicvoidrun(){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:
publicinterfaceExceptionLoggingRunnableextendsRunnable{defaultvoidrun(){try{loggedRun();}catch(Exception ex){System.err.println("Exception in Runnable: "+ ex.getMessage());
ex.printStackTrace(System.err);}}voidloggedRun();}
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...
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.