Runable和Callable区别

127 阅读2分钟

Runable和Callable区别

一、区别

  1. Callable规定的方法是call(),Runnable规定的方法是run()。
  2. Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
  3. call方法可以抛出异常,run方法不可以。
  4. 运行Callable任务可以拿到一个Future对象,Future 表示异步计算的结果。(PS: 特别注意,executorService.submit(Runnable task) 也会返回future, 但是没有future的效果)。

二、Future接口

Future接口代表异步计算的结果,通过Future接口提供的方法可以查看异步计算是否执行完成,或者等待执行结果并获取执行结果,同时还可以取消执行。

public interface Future {

  boolean cancel(boolean mayInterruptIfRunning);//取消任务

  boolean isCancelled(); //是否取消了

  boolean isDone(); //任务是否完成

  V get() throws InterruptedException, ExecutionException; //获取任务执行结果,如果任务还没完成则会阻塞等待直到任务执行完成

  V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; //等待一段时间尝试获取执行结果
}

三、Runable示例

public class RunnableTest {
    // 创建线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        Runnable task = () -> {
            System.out.println("thread name [" + Thread.currentThread().getName() + "]");
            System.out.println("task running ......");

            try {
                Thread.sleep(1000 * 20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("task end ......");
        };

        executorService.submit(task);

        // 关闭线程池
        executorService.shutdown();
    }

四、Callable示例

public class CallableTest {
    // 创建线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        // 创建task
        Callable task = () -> {
            System.out.println("Thread name [" + Thread.currentThread().getName() + "]");
            System.out.println("task running ......");
            Thread.sleep(1000 * 20);
            System.out.println("task end ......");
            return "call return";
        };

        Future result = executorService.submit(task);

        while(!result.isDone()) {
            System.out.println("waiting task end ......");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        try {
            System.out.println("thread end, return : " + result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 关闭线程池
        executorService.shutdown();
    }
}

五、submit和execute区别

  1. execute执行的是一个Runnable任务,submit 执行 Runnable和Callable都可以。
  2. execute的提交没有返回值,而submit的提交会返回一个Future类型的对象。
  3. execute提交的时候,如果有异常,就会直接抛出异常;而submit在遇到异常的时候,通常不会立马抛出异常,而是会将异常暂时存储起来,等待你调用Future.get()方法的时候,才会抛出异常。

六、总结

  1. Runnable可以提交给Thread,直接启动一个线程来执行。核心方法是run(),通过excuse()方法执行。
  2. Callable一般都是提交给ExecuteService来执行,核心方法是call(),通过submit方法执行。
  3. Runnable执行没有返回;Callable有返回。