并发编程——runnable、callable、future和futureTask详解。

并发编程——Runnable、Callable、Future和FutureTask详解

  在Java中,通过继承Thread,重写其run方法,还有就是实现Runnable接口是最常见的新建线程的两种方式,唯一不足的是这两种方式在执行完run方法之后无法得到返回值,为了优化这种情况,继而出现了Callable和Future,通过它们可以在执行完任务之后得到任务执行结果。

1. Runnable

在这里插入图片描述Runnable是一个函数式接口,被@FunctionalInterface标识,接口里面只定义了一个返回void类型的run方法,所以线程执行完成后是不会有返回值的。

2. Callable

在这里插入图片描述可以看到Callable接口和Runnable一样也被@FunctionalInterface标识,不同的是接口里面的call方法返回了一个泛型类型,但是线程是异步执行的,两个线程是互不干扰的,那我们怎么在一个线程里面获取到其他任务执行之后的结果呢?Future接口这个时候就可以派上用场了。

3. Future

当使用Callable想获取返回值的时候就需要用到Future接口,使用Future可以监视任务的执行情况,下面详细解释一下Future接口里面各个方法的作用:
在这里插入图片描述

  1. cancel
    用来取消任务,取消任务成功则返回true,否则返回false,mayInterruptIfRunning用来控制是否允许取消正在执行却没有执行完毕的任务,有以下几种情况:
  • 任务已经完成,不管mayInterruptIfRunning设置为true还是false,方法返回都是false;
  • 任务正在执行,如果mayInterruptIfRunning设置为true,则返回true,如果mayInterruptIfRunning设置为false,则返回false;
  • 任务还未执行,不管mayInterruptIfRunning设置为true还是false,都返回true。
  1. isCancelled
    任务是否被取消成功

  2. isDone
    任务是否已经完成

  3. get()
    用来获取执行结果,get方法会使当前调用线程产生阻塞,一直等到任务执行完毕才返回,然后继续向下执行代码。

  4. get(long timeout, TimeUnit unit)
    用来获取执行结果,可以指定时间,如果还没获取到结果,就直接返回null,这个就比get()方法好些,可以避免了获取不到结果让当前调用线程一直阻塞。

Future使用代码示例:

public class CallableDemo implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("CallableDemo  call");
            Thread.sleep(1000);
            return "success";
        }
    }

public class FutureDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> future = executorService.submit(new CallableDemo ());
        String result = future.get(); //产生阻塞
        System.out.println(result);
    }
}

4.FutureTask

在这里插入图片描述FutureTask是Future接口的具体实现,从上面可以看出也实现了Runnable接口。
关于FutureTask的使用可以看如下代码:

import java.util.concurrent.*;

public class FutureTaskExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 创建一个任务
        Callable<Integer> task = () -> {
            Thread.sleep(2000); 
            return 42;
        };

        // 创建一个FutureTask并包装任务
        FutureTask<Integer> futureTask = new FutureTask<>(task);

        // 创建线程执行FutureTask
        Thread thread = new Thread(futureTask);
        thread.start();

        // 主线程可以继续执行自己的流程
        System.out.println("doing something...");

        // 阻塞获取futureTask中任务的执行结果
        Integer result = futureTask.get();

        System.out.println("result: " + result);
    }
}



上一篇 java内部类最全详解(成员内部类、局部内部类、匿名内部类、静态内部类)!!!
记得点赞收藏哦!!!
下一篇 java面向对象三大特征
  • 34
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值