Runnable和Callable的区别和用法

创建线程的四种方式

Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。

其中前两种方式线程执行完后都没有返回值,后两种是带返回值的。

Runnable和Callable的区别

Runnable接口

public interface Runnable {
    void run();
}

Callable接口

public interface Callable {
    V call() throws Exception;
}

Runnable和Callable的区别

  1. Runnable执行方法是run(),Callable是call()
  2. 实现Runnable接口的任务线程无返回值;实现Callable接口的任务线程能返回执行结果
  3. call方法可以抛出异常,run方法若有异常只能在内部消化

注意

Callable接口支持返回执行结果,需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!
如果线程出现异常,Future.get()会抛出throws InterruptedException或者ExecutionException;如果线程已经取消,会爬出CancellationException

Runnable示例

public class CallableDemo {
    public static void main(String[] args) {
        //创建一个定长的核心线程和最大线程数都是1的FixedThreadPool线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        Callable callable = new Callable() {
            @Override
            public String call() throws Exception {
                Thread.sleep(3000);
                System.out.println("Thread_current="+Thread.currentThread());
                return "Hello world";
            }
        };
        System.out.println("start");
        // 执行任务并获取Future对象  
        Future future = executorService.submit(callable);

        try{
            //future.get()线程结果,会阻塞当前线程直到线程结束
            System.out.println("future.get()="+future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        System.out.println("end");

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

其它

在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:

  • 避免点继承的局限,一个类可以实现多个接口
  • 资源共享

Runnable接口和Thread之间的联系

public class Thread extends Object implements Runnable 

由此可见:Thread类也是Runnable接口的子类

你可能感兴趣的:(Runnable和Callable的区别和用法)