Получить результат запланированного задания - PullRequest
1 голос
/ 15 января 2012

Я пытаюсь изучить API параллелизма Java, и для своего упражнения я хочу запланировать периодическое выполнение задания каждые X секунд.Задание будет вычислять случайное число.

Я хочу получить результат запланированного задания, как только оно будет завершено.Я не мог сделать это только с помощью API, поэтому я взломал его.

Есть ли способ сделать это лучше, не используя механизмы низкого уровня?Я хотел бы иметь возможность удалить синхронизацию в MyRandomGiverTask.getResult() и вместо этого использовать что-то вроде ScheduledFuture.get().Но в моем коде ScheduledFuture никогда не выполняется / не завершается.Это мое текущее решение:

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;
            }
        }
    }
}

Ответы [ 2 ]

7 голосов
/ 15 января 2012

Ваша задача запланирована по фиксированной ставке.Это означает, что пока вы не отмените задание, оно будет выполняться исполнителем снова и снова с фиксированной ставкой.Единственное, что может сделать такая задача - это побочный эффект.Он не может ничего вернуть, поскольку будущее, возвращаемое исполнителем, представляет все ожидающие выполнения задачи.Кстати, вы заметите, что метод schedule принимает Callable в качестве аргумента (который может привести к чему-либо), тогда как метод sceduleAtFixedRate принимает только Runnable в качестве аргумента (который возвращает void, поэтому не может ничего вернуть).

Итак, если вы хотите напечатать результат каждого выполнения, то просто заставьте саму задачу (Runnable) напечатать свой результат, или пусть runnable поместит свой результат в очередь блокировки, и у вас будет основной поток take из очереди.Таким образом, основной поток будет заблокирован до тех пор, пока какой-либо результат не будет помещен в очередь.

2 голосов
/ 15 января 2012

Если вы хотите получить каждое случайное число, используйте BlockingQueue. запланированные задачи put() новые случайные числа в очереди и все, что они хотят, могут take() их.

также, если бы вы собирались использовать что-то вроде вашего решения, вы бы хотели использовать wait() / notify(), а не sleep().

...