How can I change a timer/ thread's delay

时间:2018-03-25 20:32:30

标签: java multithreading javafx

So I am trying to have a method which will have a timer or a thread, so I can auto save every N minutes.(N is the number of minutes) I get N from my XML file, which can be changed anytime. So far this is what I have come up with

private void autoSave(){
    Timer autoSaveTimer = new Timer();

    autoSaveTimer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            System.out.println("Auto saving :D");
            VB.save();
        }
    }, 0, autoSaveTime());
}

autoSaveTime(); just reads the number of minutes from the XMl file and converts it to milliseconds and returns the value. Currently if I change N, it doesn't change.

If there is a different approach I am welling to listen.

1 个答案:

答案 0 :(得分:2)

Consider using a scheduled service:

public class AutoSaveService implements ScheduledService<Void> {

    @Override
    protected Task<Void> createTask() {
        // retrieve data from UI. This should be done here,
        // as you should access the data on the FX Application Thread
        final MyDataType data = getDataFromUI(); 
        return new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                vb.save(data);
                return null ;
            }
        };
    }
}

You can use this as follows:

AutoSaveService autoSaveService = new AutoSaveService();
autoSaveService.setPeriod(Duration.seconds(5));
autoSaveService.start();

Calls to autoSaveService.setPeriod(...) will be reflected in the time before subsequent tasks are created.

You can also do things like

autoSaveService.setOnFailed(e -> {
    Throwable whatWentWrong = autoSaveService.getException();
    // log exception, warn user, etc...
});

Here's a SSCCE (just prints a message instead of saving data):

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class AutoSaveExample extends Application {

    @Override
    public void start(Stage primaryStage) {

        Spinner<Integer> saveIntervalSpinner = new Spinner<>(1, 60, 1);

        AutoSaveService autoSaveService = new AutoSaveService();
        autoSaveService.periodProperty().bind(Bindings.createObjectBinding(
                () -> Duration.seconds(saveIntervalSpinner.getValue()), 
                saveIntervalSpinner.valueProperty()));
        autoSaveService.start();

        VBox root = new VBox(5, new Label("Save Interval:"), saveIntervalSpinner);
        root.setAlignment(Pos.CENTER_LEFT);
        root.setPadding(new Insets(18));
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static class AutoSaveService extends ScheduledService<Void> {
        @Override
        protected Task<Void> createTask() {
            // retrieve data from UI. This should be done here,
            // as you should access the data on the FX Application Thread
//          final MyDataType data = getDataFromUI(); 
            return new Task<Void>() {
                @Override
                protected Void call() throws Exception {
//                  vb.save(data);
                    System.out.println("Save at "+System.currentTimeMillis());
                    return null ;
                }
            };
        }
    }


    public static void main(String[] args) {
        launch(args);
    }
}
相关问题