【问题标题】:Get result of scheduled task获取计划任务的结果
【发布时间】:2012-02-10 19:05:45
【问题描述】:

我正在尝试学习 java 并发 API,为了我的练习,我想安排一个作业每隔 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;
            }
        }
    }
}

【问题讨论】:

    标签: java concurrency scheduled-tasks scheduling java.util.concurrent


    【解决方案1】:

    如果要计算每个随机数,请使用 BlockingQueue。计划任务put()s 队列中的新随机数,任何想要它们的都可以take()它们。

    另外,如果您打算使用类似于您的解决方案的东西,您会想要使用wait()/notify(),而不是sleep()

    【讨论】:

      【解决方案2】:

      您的任务是按固定速率安排的。这意味着在您取消任务之前,它将由执行者以固定的速率一次又一次地执行。这样的任务唯一能做的就是产生副作用。它不能返回任何东西,因为执行器返回的未来代表了任务的所有未决执行。顺便说一句,您会注意到 schedule 方法将 Callable 作为参数(可能会导致某些结果),而 sceduleAtFixedRate 方法仅将 Runnable 作为参数(返回 void,因此无法返回任何内容)。

      所以,如果你想打印每次执行的结果,那么只需让任务本身(Runnable)打印它的结果,或者让 runnable 将它的结果放入阻塞队列,并让主线程take从队列中。主线程将因此被阻塞,直到一些结果被放入队列。

      【讨论】:

      • 如果你在等待结果,一般不想循环轮询,直接使用take即可。
      猜你喜欢
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      • 2015-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多