Java 异步调用及Callable, Future, FutureTask 原理

一 、使用方式一般为两种:

1 . 创建线程执行FutureTask并通过FutureTask得到异步结果;

public static void main(String[] args) throws ExecutionException, InterruptedException {

        long start = System.currentTimeMillis();

        // 1.创建任务,这个FutureTask可以是Callable的也可以是Runnable的
        FutureTask task = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(3000); // 模拟异步任务执行
                return "我是异步结果";
            }
        });

        // 2.创建线程执行任务
        Thread thread = new Thread(task);
        thread.start();

        // 3.主线程模拟在异步任务之间执行其他任务
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 4.得到异步任务结果
        System.out.println(task.get());

        System.out.println("运行时间 : " + (System.currentTimeMillis() - start) + "ms");
    }

运行结果:

我是异步结果
运行时间 : 6002ms

Process finished with exit code 0

 

2 . 使用线程池管理线程通过Future接口得到结果;

public static void main(String[] args) throws ExecutionException, InterruptedException {

        long start = System.currentTimeMillis();

        ExecutorService executorService = Executors.newFixedThreadPool(5);

        Future future = executorService.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(3000);
                return "我是异步结果";
            }
        });

        System.out.println("主线程工作");
        Thread.sleep(6000);

        System.out.println(future.get());

        System.out.println("运行时间 : " + (System.currentTimeMillis() - start) + "ms");
    }

 运行结果:

主线程工作
我是异步结果
运行时间 : 6012ms 

 

注意:

        异步结果用Future或者FutureTask都可以获取。Future是接口,FutureTask是实现了这个接口的实现类。FutureTask除了实现Future接口外,还实现了Runnable接口。所以不论是Callable任务还是Runnable任务都可以用FutureTask完成,而这两种都会最终都会调用Callable的call方法,对于Runnable实现调用call的方式是使用了适配器模式。

 (图片来源网上,侵删)

      debug第二个程序,我们可以看到这时定义的Future也是FutureTask实现的。

二、异步原理

1.  异步模型:

         可以总结为生产者和消费者,生产者就是线程处理任务,消费者就是调用者得到任务结果。那生产者消费者模型还有缓冲区啊,这里面就是用FutureTask中的outcome字段在任务结束后缓存结果。

2 . 异步流程:

         主线程main开启线程a执行任务,并马上返回Future,如果是刚新建任务,状态置为new。当main线程想取线程a执行的结果(调用了FutureTask的get方法)时,就查看这个任务的state是否执行完成(completing),如果还没有完成就阻塞当前线程(main)等待线程a执行完成。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值