Timer - ScheduledExecutorService wird schon vorher beendet

  • Themenstarter Themenstarter Gelöschtes Mitglied 67123
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 67123

Gast
Ich habe einen Timer, der je nach Einstellung (z. B. nach 5 Sekunden) beendet wird:
Java:
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        new Stop();
        timer.shutdown();
    }
}, (TIME_DAYS * 86400000) + (TIME_HOURS * 3600000) + (TIME_MINUTES * 60000) + (TIME_SECONDS * 1000), 1, TimeUnit.MILLISECONDS);
TIME_DAYS etc. sind Nutzereingaben, die in Millisekunden umgerechnet werden.

Jedoch habe ich das Problem, dass der Timer manchmal nach weniger als 5 Sekunden beendet wird (z. B. 2 oder 3 Sekunden). Woran liegt das oder kann es liegen?

Dieser Timer wird nach einem ActionEvent gesartet und wenn dieser Timer um ist, wird das Programm oder der Thread beendet.
 
TimerTask gehört zu Timer und ist für Executors nutzlos. Es reicht Runnable zu implementieren. timer.shutdown(); wird auch falsch verwendet. Was mir fehlt ist ein nachvollziehbarer Beweis, dass der ScheduledExecutorService den Task zur falschen Zeit ausführt.
Ich habe folgenden Code mehrfach getestet:
Java:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Main {

    public static final class Task implements Runnable {

        private final int instance;
        private final long time;

        public Task(final int instance, final long time) {
            this.instance = instance;
            this.time = time;
        }

        @Override
        public void run() {
            final long durration = (System.currentTimeMillis() - this.time) / 1000L;
            if (durration != 5L) {
                System.err.println(String.format("Instance %s failed! Executes after: %s ms", this.instance,
                        System.currentTimeMillis() - this.time));
            } else {
                System.out.println(String.format("instance %s executed after: %s seconds", this.instance, durration));
            }
        }
    }

    public static void main(final String[] args) {
        for (int i = 0; i < 100; i++) {
            final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
            executorService.schedule(new Task(i, System.currentTimeMillis()), 5, TimeUnit.SECONDS);
            executorService.shutdown();
        }
    }

}
Es kam 1 mal vor, dass der Timer bereits nach 4999 ms ausgelöst wurde. Das ist aber ganz normal. Benutzt man sehr viele solche Tasks, kann die VM diese nicht mehr parallel abarbeiten und die Tasks werden verzögert ausgeführt.
 
Ach, habe ich noch vergessen: scheduleAtFixedRate -> wozu? Wie oft soll das Programm beendet werden?
Weiteres.
Also das Beenden des Programmes war nur ein Beispiel. Lol, 20-mal beenden.
Neben einem anderen Thread soll die Mausposition gehalten werden:
Java:
// Fix mouse position
    private void fixMousePosition(Integer X_COORD, Integer Y_COORD) {
        gMI.fixMousePositionThread = new Thread(() -> {
            while (gMI.isRunning()) {
                gMI.robot.mouseMove(X_COORD, Y_COORD);
                try {
                    TimeUnit.MILLISECONDS.sleep(MOVE_MOUSE_DELAY);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        gMI.startFixMousePositionThread();
    }
Dieser Thread soll ebenfalls beendet werden, wenn ein anderer beendet wird.
Aber mir fällt gerade ein: Der obige Thread ist in einem anderen Thread drin. Heißt, der wird doch automatisch beendet, wenn der "Hauptthread" beendet wird, aber warum ist main.fixMousePositionThread.isAlive() dann noch true? Oder irre ich mich?
 
Ich zweifel mal jetzt nicht am Sinn der Maßnahme, die Maus an einer Position festzuhalten. Rutscht dann eigentlich die Maus auf dem Schreibtisch zurück in ihre ursprüngliche Position, wenn man sie verschiebt?
Ein Thread endet, wenn er mit seiner Arbeit fertig ist. Ein verlässliche Methode einen Thread anders zu beenden gibt es nicht. Wenn du also eine Schleife im Thread verwendest, musst du einfach dafür sorgen, dass die Schleifenbedingung nicht mehr erfüllt wird. Damit endet die Schleife und auch der Thread.
 
Man kann natürlich auch das gesamte Programm inklusive aller Threads mit System.exit forcieren, ansonsten ist die Schleifenbedingung die Musterlösung.
 

Zurück
Oben