FutureTask,ThreadPoolExecutor

FutureTask_UML
FutureTask设计解释
1.正真开启线程是Thread类(构造函数接受Runnable类型的参数),而Thread又继承了Runnable,执行的就是run()方法。
2.Runnable是一个任务体。
3.Callable也是一个任务体。(相较于Runnable能返回结果而已)
3.Future可以视为一个工具类
源码分析
// FutureTask实现了Runnable类,即可作为任务体传递给Thread执行
// 重写run()方法,最终都是执行Callable的call()方法
    public void run() {
            // 虚假代码.....
            Callable c = callable;
            result = c.call();              
    }

// 如果接收Runnable呢,其实就是做了一个适配转换
 public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
 }

// 可以忽略不看,就是封多了一层方法而已
 public static  Callable callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter(task, result);
    }

// 正在的转换
private static final class RunnableAdapter implements Callable {
        private final Runnable task;
        private final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            // 执行了Runnable方法的run()方法,返回值类型为传入的泛型
            task.run();
            return result;
        }
    }
FutureTask任务状态流转
  1. NEW:当FutureTask被初始创建的时候的状态。
  2. COMPLETING和NORMAL:当任务被执行完毕,FutureTask会将执行结果设置给FutureTask的outcome属性,在设置之前会将FutureTask的状态修改为COMPLETING,在设置之后会将FutureTask的状态修改为NORMAL。
  3. EXCEPTIONAL:当任务在被执行的过程中抛了异常,FutureTask会将异常信息设置给FutureTask的outcome属性,在设置之前会将FutureTask的状态修改为COMPLETING,在设置之后会将FutureTask的状态修改为EXCEPTIONAL。
  4. CANCELLED:当外部想要取消任务,而又不允许当任务正在执行的时候被取消的时候会将FutureTask的状态修改为CANCELLED。
  5. INTERRUPTING和NTERRUPTED:当外部想要取消任务,同时允许当任务正在执行的时候被取消的时候,会先将FutureTask的状态设置为INTERRUPTING,然后设置执行任务的线程的中断标记位,最后将Future的状态设置为INTERRUPTED。
FutureTask的状态流转可能流程
NEW—>COMPLETING—>NORMAL(任务执行正常)。
NEW—>COMPLETING—>EXCEPTIONAL(任务执行异常)。
NEW—>CANCELLED(不允许执行中的取消)。
NEW—>INTERRUPTING—>INTERRUPTED(允许执行中的取消)。
Future相关方法解析
// 返回值 :已完成或者已取消的前提下调用将返回false;true表示取消成功(任务将不再被执行,)。
// 参数:true表示停止正在执行的任务;false表示不打断正在执行的任务,任务可以正常完成;
 boolean cancel(boolean mayInterruptIfRunning);

  // 重点示例:先调用了cancel(参数无论是true/false),这时候再启动线程任务将不被执行
 FutureTask futureTask = new FutureTask(new Runn5());
 futureTask.cancel(true);
 Thread thread = new Thread(futureTask);
 thread.start();

// 其实就是cancel()的返回值
 boolean isCancelled();

// 任务被取消或者已完成,以及发生异常终止,都将返回true
 boolean isDone();

// 线程阻塞获取结果
V get() throws InterruptedException, ExecutionException,CancellationException;

// 线程 阻塞获取结果,传入等待时长,超过等待时长抛出TimeoutException
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, CancellationException,TimeoutException;

ThreadPoolExecutor
ThreadPoolExecutor_UML

按照默认线程池是实现ExecutorService接口的,按照ExecutorService接口定义的行为,我们可以将Runnable或Callable任务提交到线程池让其去被执行,而被提交的Runnable或Callable任务都会被包装成FutureTask,丢到任务队列,由线程池的工作线程去执行。使用线程池不仅可以提高应用的响应时间,还可以避免”java.lang.OutOfMemoryError: unable to create new native thread” 之类的错误。

ExecutorService方法解析
// 提交任务执行,在调用此方法前调用了shutdown()则会报RejectedExecutionException异常
 Future submit(Callable task);
// 线程池会停止接受新的任务,但会完成已提交的任务
void shutdown();
// 返回已提交还没执行的线程,对于正在执行的任务一般会调用interrupt方法尝试中断
List shutdownNow();
// 判断是否执行了shutdown或者shutdownNow()方法
boolean isShutdown();
//获取所有任务是否已经结束,当调用shutdown或者shutdownNow方法后,并且所有提交的任务完成后返回为true
boolean isTerminated();
// 阻塞等待所有任务结束,可以设置timeout,如果超时了所有任务还未完成则返回false,反之
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
// 批量提交任务,整个过程为阻塞,是因为内部执行了Future.get(),所有任务都执行完毕后才返回。
 List> invokeAll(Collection> tasks) throws InterruptedException;
// 和上面方法相同,只是了限定时间
 List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException;

你可能感兴趣的:(FutureTask,ThreadPoolExecutor)