Callable和Future、FutureTask

Java中除了Runnable接口,还有Callable接口。
两者区别是,后者可以有返回值,一般用于耗时计算。
Runnable接口在线程中用得比较多,一般可以作为线程执行体,Callable一般会与FutureTask结合使用。

Callable接口的源码如下:

/**
 * A task that returns a result and may throw an exception.
 * Implementors define a single method with no arguments called
 * {@code call}.
 * 带有返回值的任务,可能抛出异常。
 * 
 * <p>The {@code Callable} interface is similar to {@link
 * java.lang.Runnable}, in that both are designed for classes whose
 * instances are potentially executed by another thread.  A
 * {@code Runnable}, however, does not return a result and cannot
 * throw a checked exception.
 * Callable接口类似于Runnable接口,都是设计用于被其他线程执行的类实例。
 * 但是Runnable接口不返回结果,不能抛出一个受检异常。
 * 
 * <p>The {@link Executors} class contains utility methods to
 * convert from other common forms to {@code Callable} classes.
 * Executors类包含将其他通用形式转成Callable类的辅助类。
 * 
 * @see Executor
 * @since 1.5
 * @author Doug Lea
 * @param <V> the result type of method {@code call}
 */
@FunctionalInterface
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;
}

Future接口用于表示异步计算的结果,该接口包含检查计算是否结束、等待计算结束、获取计算结果的方法。
其中get()可以获取计算结果,在计算完成之前,会一直阻塞当前线程。计算可以被取消。

FutureTask实现了RunnableFuture接口:

public class FutureTask<V> implements RunnableFuture<V> {

而RunnableFuture接口继承自Runnable和Future:

public interface RunnableFuture<V> extends Runnable, Future<V> {

FutureTask表示可取消的异步计算,作为Future接口的实现。FutureTask可以包装Runnable接口,
另外因为实现了Runnable接口,所以可以提交给Executor执行。

下面用代码测试一下:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class Main {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

    Runnable runnable = new Runnable() {

        @Override
        public void run() {
        System.out.println("runnable running");
        }
    };

    Callable<Integer> callable = new Callable<Integer>() {

        @Override
        public Integer call() throws Exception {
        System.out.println("callable running");

        return 123;
        }
    };

    Callable<Integer> callable1 = new Callable<Integer>() {

        @Override
        public Integer call() throws Exception {
        System.out.println("callable1 running");

        return 123;
        }
    };

    //runnable
    Thread thread1 = new Thread(runnable);
    thread1.start();

    //callable
    FutureTask<Integer> future = new FutureTask<Integer>(callable);
    Thread thread2 = new Thread(future);
    thread2.start();

    System.out.println("future is done? "+future.isDone());
    //future.cancel(false);
    Thread.sleep(1000);
    System.out.println("future result: "+future.get());

    ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L,
        TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

    executor.execute(runnable);

    FutureTask<Integer> future1 = new FutureTask<Integer>(callable1);
    executor.execute(future1);

    FutureTask<String> ft = new FutureTask<String>(runnable, "aaaaa");
    Thread thread3 = new Thread(ft);
    thread3.start();
    while(!ft.isDone()){
        Thread.sleep(1000);     
    }
    System.out.println("future runnable result: "+ft.get());

    Future<Integer> futureTask = executor.submit(callable);
    while(!futureTask.isDone()){
        Thread.sleep(1000);     
    }
    System.out.println("futureTask result: "+futureTask.get());
    executor.shutdown();


    }
}

输出结果:

runnable running
future is done? false
callable running
future result: 123
runnable running
callable1 running
runnable running
future runnable result: aaaaa
callable running
futureTask result: 123

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页