同時学習プログラム-FutureTask強力なクラス03

3628 ワード

FutureTaskを学ぶ前に、私たちはまずインタフェース--RunnableFutureを理解しなければなりません.
このインタフェースは何ですか、皆さんに見せてください.
public interface RunnableFuture extends Runnable, Future {
  void run();
}

これは簡単なインターフェースでしょう.
RunnableとFutureクラスを継承すると、runnableは言わず、runnableもインタフェースであり、runメソッドもあります.私たちは普段runnableでThreadと一緒に使っています.だからrunnableは実行する内容で、いったい何を実行するのか、私たちは自分で決めます.実現すべきrunメソッドがあるのではないでしょうか.
Futureとは何か、『ExecutorServiceとFutureの関係』という記事でお話ししました.
これはたぶん運行結果を得ることができるもので、もちろん彼は運行結果を得るだけでなく、任務を中断することもできます.
だからRunnableFutureはRunnableとFutureを同時に継承した、つまり.
RunnableFutureは、何を実行するかを知っているだけでなく、実行を中断する能力もあります.
しかしRunnableFutureもただのインタフェースで、このインタフェースが何をすべきかを定義しただけです.キャンセル方法に画像をダウンロードするコードを書かなければならないなら、まだできません.
余計なことは言わないで、RunnableFutureは1つのものを定義して、これは任務を実行することができて、また任務を中断することができます.
定義にすぎませんが、RunnableFutureの具体的な実装クラスであるFutureTaskを見てみましょう.
やっと本題に着きましたね.
FutureTaskのソースコードは少なく、500行未満ですが、ソースコードはすごいですが、読むのはお勧めしません.私たちが知らないクラスの一部にもつながっているからです.
FutureTaskがRunnableFutureを継承し、具体的な実装クラスである以上、これを直接使用できることを示しています.
また、タスクを指定して何を実行するか、タスクを中断することもできるので、便利なクラスですね.
このクラスを学ぶ方法は、直接使うことをお勧めします.
このクラスはRunnableを継承しているので、runnableとして使用することができます.runnable私たちは普段どのように使っていますか.
簡単な例を挙げます.
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("hi runnable");
    }
};
new Thread(runnable).start();

だから、FutureTaskもこのように使うことができて、例を挙げます.
FutureTask futureTask = new FutureTask(new Callable() {
    @Override
    public String call() throws Exception {
        System.out.println("hi futureTask");
        return null;
    }
});
new Thread(futureTask).start();

ちょっと違う感じがしますが、前に言ったことを覚えていますか.FutureTaskはタスクを実行するだけでなく、結果を得ることができるので、このクラスには結果を一般的に指すことができるのではないでしょうか.
結果が出た以上、実行中に結果を返すのは合理的でしょう.
この結果は何でも可能であり、実際の開発で直面する問題を挙げることができます.--画像の例をダウンロードします.
FutureTask futureTask = new FutureTask(new Callable() {
    @Override
    public String call() throws Exception {
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(500);
            System.out.println(" :" + (i / 10.0 * 100) + "%" + "( )");
        }
        return " ";
    }
});

new Thread(futureTask).start();

try {
    System.out.println(futureTask.get());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

コードが少し多いので、見終わってしまいました.簡単です.
シミュレーションで1枚の画像をダウンロードし、最後にこの画像を得たので、実行結果はこうです.

 :10.0%( )
 :20.0%( )
 :30.0%( )
 :40.0%( )
 :50.0%( )
 :60.0%( )
 :70.0%( )
 :80.0%( )
 :90.0%( )
 :100.0%( )
 

コードを見終わって何か質問はありませんか?
疑問があるはずだよ.
スレッドでこの画像をダウンロードしますが、メインスレッドで直接印刷しているので、ポインタを空にしないのではないでしょうか.まだダウンロードが終わっていないうちに印刷文を実行しているのではないでしょうか.空のポインタでしょうか.
これがFutureTaskのすごいところで、getメソッドを呼び出すと、getが届かなければgetメソッドのところにブロックされ、getが届くまでブロックされます.
コードを2行追加して、そうかどうか見てみましょう.
 long startTime = System.currentTimeMillis();
 System.out.println(futureTask.get());
 System.out.println(" :" + (System.currentTimeMillis() - startTime));

簡単に時間をかけて判断しますよね?
実行結果:
 
 :5047

だからずっとそこに詰まっています.前に「ArrayBlockingQueueとLinkedBlockingQueue」を話したとき、このような渋滞を話したことがあります.たぶんこのような渋滞です.
FutureTaskが中断されたことを覚えていますか?cancel(boolean mayInterruptIfRunning)を使用してタスクを中断することができます.
パラメータの意味は、中断された場合、実行を続行するかどうかです.
この類の話の差は多くないような気がします.
what a nice class!