Callable、Future、Runnable、FutureTask的联系与区别

① Runnable
它是一个接口,在它里面只声明了一个run()方法:

    public interface Runnable {
        public abstract void run();
    }

由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。
使用:实现Runnable接口,重写run()方法。
class RunnableImpl implements Runnable
作为创建线程的参数:Thread thread = new Thread (Runnable RunnbaleImpl);
作为要执行的任务提交到线程池:threadPool.submit (Runnable RunnableImpl);
或者是threadPool.execute (Runnable RunnableImpl);
② Callable
是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做call():

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

call()方法返回泛型V,所以提交Callable接口返回Future接口类,并且会抛出异常。
使用:
A. 定义MyClass实现Callable接口;
class CallabImpl implements Callable
B. 重写call(),将执行的代码写入;
C. 将CallableImpl包装成FutureTask对象;
FutureTask实现了Runnable和Future接口,可以当作Runnable接口耐心hi用。FutureTask通过在run()内部调用call()来执行任务,并保存了call()的返回值;
FutureTask runnable = new FutureTask(new CallableImpl ());
D. 创建Thread的对象,也可以提交到线程池执行;
Thread thread = new Thread(runnable);//传入参数Runnable接口
threadPool.submit(runnable);//execute()也可以
E. 此外Callable对象也可以单独提交到线程池执行;
Future submit(Callable task);
③ Runnable和Callable运用:配合线程池使用
Future submit(Callable task);//多
Future submit(Runnable task, T result);//少
Future<?> submit(Runnable task);//execute()方法也行,只是没有返回值.
不管是Runnable还是Callable,在提交任务至线程池的过程中会被包装成RunnableFuture供内部execute()使用。

    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

④ Future
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
比如向线程池提交任务,返回Future.

<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);

Future类位于java.util.concurrent包下,它是一个接口:

    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws InterruptedException, ExecutionException;
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }

1) cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。
① 如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;
② 如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;
③ 如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
2) isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
3) isDone方法表示任务是否已经完成,若任务完成,则返回true;
4) get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
5) get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
总结:Future提供了三种功能:
  1)判断任务是否完成;
  2)能够中断任务;
  3)能够获取任务执行结果。
⑤ FutureTask:实现了Runnable和Future接口(后者的唯一实现类)
Future只是一个接口,所以是无法直接用来创建对象使用的,一般是采用它的唯一实现类FutureTask。

public class FutureTask<V> implements RunnableFuture<V>

public interface RunnableFuture<V> extends Runnable, Future<V> {
        void run();
}

可以看出FutureTask实现了RunnableFuture接口,而RunnableFuture继承了Runnable接口和Future接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章