【多线程】Callable详解

本文详细介绍了Java中的Callable接口,其与Runnable的区别,以及如何通过FutureTask和线程池实现Callable任务的执行和结果获取。主要内容包括Callable接口的使用、FutureTask的作用以及两种常见的Callable实现方法。
摘要由CSDN通过智能技术生成

Callable接口

先看看Callable接口的源码:
在这里插入图片描述
Callable是一个函数式接口,此时就可以用lambda表达式更简洁地使用它。Callable是个泛型接口,只有一个方法call,该方法返回类型就是传递进来的V类型。call方法还支持抛出异常.
与Callable对应的是Runnable接口,实现了这两个接口的类都可以当做线程任务递交给线程池执行,Runnable接口的源码如下:
在这里插入图片描述
Runnable和Callable的区别:

  • Runnable接口里执行线程任务是在run方法里写的,Callable接口里执行线程任务是在call方法里写;
  • Callable的任务执行后可返回值,而Runnable的任务是不能返回值得;
  • call方法可以抛出异常,run方法不可以;
  • 加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用ExecutorService的submit方法;
  • 运行Callable任务可以拿到一个Future对象,表示异步计算的结果.Future对象封装了检查计算是否完成、可取消任务的执行,检索计算的结果的方法;

Further接口

Further接口的源码如下:
在这里插入图片描述

  • Future是一个接口,代表了一个异步计算的结果。接口中的方法用来检查计算是否完成、等待完成和得到计算的结果。
  • get()方法 : 当计算完成后,只能通过get()方法得到结果,get方法会阻塞直到结果准备好了。
  • cancel()方法 : 如果想取消,那么调用cancel()方法,但如果计算完了,就不能调用cancel方法了。
  • isCanceled()方法 : 检查任务是否被取消成功了.
  • isDone()方法 : 检查任务是否完成 。

FutureTask类

  • Future是一个接口,FutureTask是Future接口的唯一实现类,一般用的时候向上转型,使用Future。
  • FutureTask类实现的是RunnableFuture接口.
  • 该接口继承了Runnable接口和Future接口,因此FutureTask类既可以当做线程任务递交给线程池执行,又能当Callable任务的计算结果。
  • FutureTask可以用来包装Callable或者Runnbale对象。因为FutureTask实现了Runnable接口,所以FutureTask也可以被提交给Executor

Callable的两种实现方法

一.使用FutureTask实现

  • 创建一个类,如MyCallableTask,实现Callable接口。
  • 在MyCallableTask类中重写call()方法,定义线程需要执行的操作。
  • Callable接口的call()方法可以有返回值,并且能够抛出异常。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

//定义实现Callable接口的的实现类重写call方法。
public class MyCallableTask implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        //TODO 线程执行方法
        return -1;
    }
}
public class Test7 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建Callable对象
        Callable<Integer> mycallabletask = new MyCallableTask();
        //开始线程
        FutureTask<Integer> futuretask = new FutureTask<Integer>(mycallabletask);
        new Thread(futuretask).start();
        //通过futuretask可以得到MyCallableTask的call()的运行结果:
        futuretask.get();
    }
}

二.使用线程池实现

举两个例子:

  public class CallableTest {
      public static void main(String[] args) throws ExecutionException, InterruptedException,TimeoutException{
          //创建一个线程池
          ExecutorService executor = Executors.newCachedThreadPool();
          //使用submit()方法来执行线程,此处使用的是lambda表达式
          Future<String> future = executor.submit(()-> {
                  TimeUnit.SECONDS.sleep(5);
                  return "CallableTest";
          });
          System.out.println(future.get());
          executor.shutdown();
      }
  }

   public class CallableAndFuture {      
       public static void main(String[] args) {
           Random random = new Random();
           //创建一个线程池
           ExecutorService threadPool = Executors.newSingleThreadExecutor();
           Future<Integer> future = threadPool.submit(new Callable<Integer>() {
               public Integer call() throws Exception {
                   return random.nextInt(10000);
               }
           });
           try {
               Thread.sleep(3000);
               System.out.println(future.get());
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
   }

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值