Question

I am trying to learn the java concurrency API, and for my exercise i want to schedule a job to run periodically every X seconds. The job will compute a random number.

I want to get the result of the scheduled task as soon as it is finished. I could not get this done only with the API so i hacked it.

Is there a way to do this better, without using low level mechanisms? I would like to be able to remove the synchronization in MyRandomGiverTask.getResult() and instead use something like the ScheduledFuture.get(). But in my code ScheduledFuture is never done/completed. This is my current solution:

class A {
    public static void main() {
        MyRandomGiverTask task = new MyRandomGiverTask(200);
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        ScheduledFuture<Double> scheduledDouble =
            (ScheduledFuture<Double>) scheduler
                .scheduleAtFixedRate(task, 1, 4, TimeUnit.SECONDS);
        while (true) {
            System.out.println(" >> " + task.getResult());
        }
    }
    public class MyRandomGiverTask implements Runnable {
        MyRandomGiver giver = new MyRandomGiver();
        int param;
        double result;
        public MyRandomGiverTask(int param) { this.param = param; }
        @Override public void run() { result = giver.getRandom(param); }
        public double getResult() {
            try {
                while (result == 0d) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return result;
            } finally {
                result = 0d;
            }
        }
    }
}
Was it helpful?

Solution

If you want to get every random number computed, use a BlockingQueue. the scheduled tasks put()s new random numbers in the queue and whatever wants them can take() them.

also, if you were going to use something like your solution, you would want to use wait()/notify(), not sleep().

OTHER TIPS

Your task is scheduled at fixed rate. This means that until you cancel the task, it will be executed again and again by the executor with a fixed rate. The only thing that such a task can do is to have a side-effect. It can't return anything, since the future that is returned by the executor represents all the pending executions of the task. BTW, you'll notice that the schedule method takes a Callable as argument (which can result something), whereas the sceduleAtFixedRate method only takes a Runnable as argument (which returns void, thus can't return anything).

So, if you want to print the result of each execution, then simply make the task itself (the Runnable) print its result, or have the runnable put its result in a blocking queue, and have the main thread take from the queue. The main thread will thus be blocked untile some result is put in the queue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top