同時学習プログラム-AbstractExecutorServices 04

4076 ワード

今日勉強するクラスはAbstractExecutorServiceですが、このクラスは名前によって推測の方向があるのではないでしょうか.
前の『Executor、ExecutorServiceとFutureの関係』で、ExecutorServiceについて話したことがあります.
当時ExecutorServiceというクラスは主にタスクを実行するためだと言われていました.正確には、インタフェースのはずです.
そこで今日はExecutorServiceの具体的な実装クラス、すなわちAbstractExecutorServiceを見てみましょう.
彼が具体的に実現したと言っても正確ではありません.結局は抽象的なクラスにすぎないので、以下のようにします.
public abstract class AbstractExecutorService implements ExecutorService

その前に、ExecutorServiceがどのようなインタフェースメソッドを予約しているのかを説明します.
これらの方法は大体この4つのスタイルです.shutdown代表クローズタスクTerminated代表中断タスクsubmit提供runnable実行タスクinvoke実行するタスクの準備ができている
AbstractExecutorServiceはすでにsubmitとinvokeタイプの方法を自主的に実現しており、つまりタスクの手配を規定しているので、AbstractExecutorServiceというクラスを使用するには、痛くも痒くもないshutdownとTerminatedタイプの方法を実現するだけでよい.
中断タスクを閉じる方法を自発的に実現しないと仮定すると、このクラスは直接使用できるのではないでしょうか.
もちろんいいです.
しかし、具体的な例を挙げる前に、AbstractExecutorServiceクラスの内部に新しい方法を理解しておきましょう.これらの方法は、前の記事で述べたFutureTaskクラスに関連しています.興味のある人は、まず「FutureTaskの強力なクラス」を見てみましょう.
ここでFutureTaskクラスの役割をもう一度お話しします.FutureTaskはタスクを実行したり、タスクを中断したりできるクラスです.
AbstractExecutorServiceを見続け、この方法を見てみましょう.
protected  RunnableFuture newTaskFor(Callable callable) {
    return new FutureTask(callable);
}

AbstractExecutorService内部では、タスクを実行するためにFutureTaskを新規作成する方法が提供されています.その後、このFutureTaskはいつでも中断されることができます.
では、AbstractExecutorServiceについて続けて、簡単に使えるsubmitタイプの方法についてお話しします.
前述したように、submitはrunnable実行タスクを提供するので、submitの方法はrunnableを渡す必要があります.例を挙げます.
AbstractExecutorService abstractExecutorService = new AbstractExecutorService() {
    @Override
    public void shutdown() {
    }
    @Override
    public List shutdownNow() {
        return null;
    }
    @Override
    public boolean isShutdown() {
        return false;
    }
    @Override
    public boolean isTerminated() {
        return false;
    }
    @Override
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        return false;
    }
    @Override
    public void execute(Runnable command) {
        command.run();
    }
};
abstractExecutorService.submit(new Runnable() {
    @Override
    public void run() {
        System.out.println("hi");
    }
});

上記のコードは、AbstractExecutorServiceが私たちに残した抽象的な方法をほとんど実現していないので、execute実行方法を実現しました.この方法を実現しなければ、タスクは実行されません.だから、私も簡単にこの方法を実現しました.
運行結果は自然にhiで、これは何も言うことはありません.
submitタイプの方法は非常に簡単だと言ったことがありますが、上記のnewTaskFor方法を使って、ソースコードをちらっと見て、多く見てはいけません.ちらっと見てください.
public Future> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

次に、少し複雑なinvokeシリーズの方法を見てみましょう.
前述したように、invokeは実行されるタスクを準備しています.
実行されるタスクは多いので、invokeシリーズの方法はすべて集合にフックして、タスクに満ちた集合を渡して、AbstractExecutorServiceに捨てて彼にすべて実行させて、実行が終わった後、また私たちに結果を返してくれるので、使用状況はこうです.
ArrayList> taskList = new ArrayList<>();
taskList.add(new Callable() {
    @Override
    public String call() throws Exception {
        return "a";
    }
});
taskList.add(new Callable() {
    @Override
    public String call() throws Exception {
        return "b";
    }
});
try {
    List> futures = abstractExecutorService.invokeAll(taskList);
    for (Future stringFuture : futures) {
        String s = stringFuture.get();
        System.out.println(s);
    }
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

印刷結果はもちろんabです.ここで注意するのは、すべてのタスクが実行された後でこそ、結果を得ることができます.
AbstractExecutorServiceについては、主にこれだけですが、抽象クラスです.しかし、内部ではタスクの管理が実現されており、タスクを渡して結果を得るだけです.
ここでAbstractExecutorServiceクラスの特徴をまとめます:1.タスクと中断タスクを直接実行することができます(中断タスクのコードは私たちが自分で実現する必要があります).実行するタスク3を管理する.すべてのタスクが実行された後、戻り値を得ることができます(正直に言うと、これは状況によって、戻り値があるかどうかを選択することができます.どうせ人はあなたにこのメカニズムを提供しました)
総じてAbstractExecutorServiceは、タスクを実行するためです.