Search code examples
javaspringspring-bootjava-8

Set a timer on a Spring API and return something


I have a Java 1.8 Spring backend (Java version must be 1.8) which manages a heater simulator. This backend keeps track of the desired temperature for instance and makes sure that the heater maintains it.

Now I'm adding a method to set a temperature and a time and make sure the heater heats up to the desired temperature on the desired time. I was thinking of implementing this with multithreading, but it seems to be quite different from what I'm used to in C# and I'm not sure if it would be the best implementation.

Currently if someone sends a request to the API to set the timer it waits for a response until the request times out or until the given time is reached. Meanwhile the API is still reachable by other requests, but it's still a bad implementation.

Here is my current code with multithreading attempt:

// in APIController.java, execution of timer logic starts here
@GetMapping("/timer")
    public String timer(@RequestParam(value = "time", defaultValue = "ERROR") String time,
                        @RequestParam(value = "temperature", defaultValue = "15.0") String temperature) {
        try {
            LocalTime timer = LocalTime.parse(time);
            double desiredTemperature = Double.parseDouble(temperature);
            BackendController.getInstance().setTimer(timer, desiredTemperature);

            return timer.toString() + " " + desiredTemperature; // Returns only when timer completes
        } catch (DateTimeParseException | NumberFormatException e) {
            return e.toString();
        }
    }

...

// in BackendController.java
// Singleton implementation

public void setTimer(LocalTime timer, double timerTemp) {
    try {
        Duration duration = Duration.between(LocalTime.now(), timer);
        System.out.println("\n\nSetting a timer for " + timer.toString() + " with desired temperature " + timerTemp);

        synchronized (singleton) { // Not sure what's the correct way to do this
            singleton.wait(duration.toMillis());

            desiredTemp = timerTemp;
            System.out.println("\n\nSet desired temperature " + desiredTemp + " with timer trigger.");
        }
    } catch (InterruptedException e) {
        System.out.println(e.toString());
    }
}

Basically my question boils down to these two points:

  1. Is my thought process correct? Would an implementation like this work for what I want?
  2. If not, what will?

Solution

  • After some work and a lot of Googling I got it to work! Following the tutorials over at https://jenkov.com/tutorials/java-concurrency/index.html gave me a better insight into how Multithreading works and how to implement it. Here's the updated, working code:

    public void setTimer(LocalTime time, double timerTemp) {
            Thread timer = new Thread(() -> {
                try {
                    Duration duration = Duration.between(LocalTime.now(), time);
                    System.out.println("\n\nSetting a timer for " + time.toString() + " with desired temperature " + timerTemp);
    
                    Thread.sleep(duration.toMillis());
    
                    BackendController.desiredTemp = timerTemp;
                    System.out.println("\n\nSet desired temperature " + BackendController.desiredTemp + " with timer trigger.");
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            });
            timer.start();
        }