写点什么

Java 多线程 Callable 和 Future

作者:Yeats_Liao
  • 2022-10-16
    江西
  • 本文字数:2066 字

    阅读完需:约 1 分钟

一、说明

Java 提供了三种创建线程的方法


  • 实现 Runnable接口

  • 继承 Thread类本身

  • 通过 CallableFuture 创建线程


Callable 和 Future 的引入


  • 继承Thread或实现Runnable接口,任务执行完成后无法获取执行结果

  • 而要获取执行结果,必须通过共享变量或者使用线程通信的方式来达到效果

  • Java 1.5 开始引入了CallableFuture,执行任务完成后可获取执行结果,简单来说就是一个产生结果,一个拿到结果


ExecutorService


  • ExecutorService是 Java 中对线程池定义的一个接口,继承Executor接口,用于管理线程对象,可以使用 Executors工厂类来创建ExecutorService的实例(即线程池)


ExecutorService executorService1 = Executors.newSingleThreadExecutor();  ExecutorService executorService2 = Executors.newFixedThreadPool(10);  ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
复制代码


  • ExcutorService提供的三种方法都有相应的结果返回


<T> Future<T> submit(Callable<T> task);<T> Future<T> submit(Runnable task, T result);Future<?> submit(Runnable task);
复制代码


  • 同时Executors类提供方法能把Runnable对象包装成Callable对象


    public static Callable<Object> callable(Runnable task) {        if (task == null)            throw new NullPointerException();        return new RunnableAdapter<Object>(task, null);    }
复制代码


    public static <T> Callable<T> callable(Runnable task, T result) {        if (task == null)            throw new NullPointerException();        return new RunnableAdapter<T>(task, result);    }
复制代码

二、理解

Callable


  • java.lang包下Runnable接口.run()方法返回类型为void


public interface Runnable {    public abstract void run();}
复制代码


  • java.util.concurrent包下Callable接口,.call()方法返回的类型为传递进来的V - Value(值)类型


public interface Callable<V> {    V call() throws Exception;}
复制代码


实现方法


  • RunnableCallable实现类使用ExecutorSevice接口的.submit()方法提交,不使用没有返回值的.execute()方法


Future


  • java.util.concurrent包下Future<V>接口,对RunnableCallable对象执行任务完成后获取执行结果


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;}
复制代码


  • mayInterruptRunning 表示是否中断执行中的线程

  • boolean cancel() 尝试取消任务的执行,如果任务已经完成或已被取消,则返回 false;如果任务已经启动,将以中断执行线程的方式停止该任务,停止成功则返回 true

  • boolean isDone()若任务完成,则返回 true

  • boolean isCancelled() 若任务在完成前取消,则返回 true

  • get() 获取执行结果,必须等待任务完成后才返回结果

  • get(long timeout, TimeUnit unit) 获取执行结果,timeout 表示等待的最长时间,unit 表示时间单位,在指定时间内还没获取到结果,则返回 null

三、实现

1.实现接口

创建CallableThreadDemo类实现Callable接口


public class CallableThreadDemo implements Callable{    @Override    public String call() throws Exception {        System.out.println("Callable子线程: " +Thread.currentThread().getName()+ " 开启");        return "我是Callable子线程: " +Thread.currentThread().getName()+ " 产生的结果";    }}
复制代码

2.执行线程

创建CallableTest类执行测试,将创建好的线程对象通过.submit()方法提交到线程池去执行,线程执行后,返回值Future可被拿到


public class CallableTest {    public static void main(String[] args) {        // 1.创建线程池        ExecutorService executorService = Executors.newSingleThreadExecutor();        // 2.创建Callable子线程对象任务        CallableThreadDemo callableThread_1 = new CallableThreadDemo();        // 3.提交任务到线程池        Future future = executorService.submit(callableThread_1);        // 4.获取执行结果        try {            System.out.println("主线程开始执行");
System.out.println("主线程要取得Callable子线程的结果"); if (future.get()!=null){ //输出获取的结果 System.out.println(future.get()); }else { //输出未获取到结果 System.out.println("future.get()未获取到结果"); } } catch (InterruptedException e){ e.printStackTrace(); }catch (Exception e) { e.printStackTrace(); } // 5.关闭线程池 executorService.shutdown(); System.out.println("主线程执行完成"); }}
复制代码



发布于: 刚刚阅读数: 3
用户头像

Yeats_Liao

关注

Hello,World! 2022-10-02 加入

这里更多的是记录个人学习,如果有侵权内容请联系我! 个人邮箱是:yeats_liao@foxmail.com

评论

发布
暂无评论
Java多线程 Callable和Future_后端_Yeats_Liao_InfoQ写作社区