1

私は 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;
            }
        }
    }
}
4

2 に答える 2

7

あなたのタスクは固定レートでスケジュールされています。これは、タスクをキャンセルするまで、エグゼキューターによって固定レートで何度も実行されることを意味します。そのようなタスクができる唯一のことは、副作用を持つことです。executor によって返される future はタスクの保留中のすべての実行を表すため、何も返すことはできません。ところで、このscheduleメソッドは Callable を引数として取りますが (結果として何かを返す可能性があります)、sceduleAtFixedRateメソッドは Runnable のみを引数として取ります (これは void を返すため、何も返すことができません)。

したがって、各実行の結果を出力したい場合は、単純にタスク自体 (Runnable) に結果を出力させるか、Runnable にその結果をブロッキング キューに入れさせ、takeキューからメイン スレッドを取得させます。したがって、何らかの結果がキューに入れられるまで、メインスレッドはブロックされます。

于 2012-01-15T13:30:35.503 に答える
2

すべての乱数を計算したい場合は、BlockingQueue を使用します。スケジュールされたタスクput()のキュー内の新しい乱数と、それらを必要とするものは何でもそれらを実行できtake()ます。

また、ソリューションのようなものを使用する場合は、ではなく / を使用する必要ありwait()ます。notify()sleep()

于 2012-01-15T13:30:47.343 に答える