JUC并发编程(七)-Thread与Callable之间的适配类FutureTask

本文介绍了Java并发编程中的Callable接口和Thread类的关系,重点讲解了作为适配器的FutureTask类,它允许将Callable任务提交到线程池并处理结果。通过FutureTask,我们可以实现线程的异步执行并获取带有返回值的结果,同时利用其缓存特性提高程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7、Callable

线程创建方式 Thread、Runnable、Callable区别:

1、是否有返回值

Runnable 没有返回值,Callable有返回值

2、是否跑出异常

Runnable 没有异常,Callable有异常

3、方法不同, run(),call()

Runnable 运行的方法是run,Callable运行的方法是call

7.1. Thread与Callable之间的适配类:FutureTask

FutureTask是一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务和结果进行等待、获取,并判断是否已经完成、取消任务等操作。由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。

Thread创建线程,只能与Runnable有联系,与Callable没有关系,看官方API文档。

在这里插入图片描述

Thread怎么创建Callable线程呢?

在设计模式中建立两者之间的关系经常使用适配器,我们去查找jdk官方文档,看能否找到Thread和Callable相互之间有关联的类。

1、查看Runnable官方文档

在这里插入图片描述

2、查看Runnable子类

Thread能够引入Runnable,就能引入它的子类,我们看一下它的子类里面哪些有Callable相关的影子。

在这里插入图片描述

3、找到Thread与Callable的万能桥:FutureTask

​ 我们在FutureTask类的构造器中找到了Callable。于是我们就可以利用FutureTask来与Callable建立关系。FutureTask成为Thread中万能的桥。

在这里插入图片描述

怎么使用呢?看以下示例:

package com.interview.concurrent.futuretask;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author yangxj
 * @description 描述:创建线程的方法:
 * 1、Thread(Runnable)
 * 2、Thread(RunnableFuture)
 * 3、Thread(FutureTask)
 * @date 2020/2/23 0:55
 */
public class ThreadFutureTask {
    public static void main(String[] args) {

        MyCallable callable = new MyCallable();
        // 适配类
        FutureTask task = new FutureTask(callable);
        // 执行线程
        new Thread(task).start();
        // 获取返回值, get()
        try {
            System.out.println(task.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

class MyCallable implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("我Callable被调用了");
        return "callable";
    }
}

7.2. Callable有什么优点

Callable 优点:

缓存: 结果缓存!效率提高N倍

结果获取会阻塞:task.get() 获取值的方法一般放到最后,保证程序平稳运行的效率,因为他会阻塞等待结果产生!

package com.interview.concurrent.futuretask;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/**
 * @author yangxj
 * @description 描述:创建线程的方法:
 * 1、Thread(Runnable)
 * 2、Thread(RunnableFuture)
 * 3、Thread(FutureTask)
 * @date 2020/2/23 0:55
 */
public class ThreadFutureTask {
    public static void main(String[] args) {

        MyCallable callable = new MyCallable();
        // 适配类
        FutureTask task = new FutureTask(callable);
        /**
         *  @description:执行线程
         *  以下两个线程只会调用一次,为什么呢?
         *  结果缓存!,第一个线程执行的结果,已经做了缓存,这样线程的效率会提高N倍
         *
         */
        new Thread(task,"A").start();
        new Thread(task,"B").start();
        // 获取返回值, get()
        try {
            // 细节2:task.get() 获取值的方法一般放到最后,保证程序平稳运行的效率,因为他会阻塞等待结果产生!
            System.out.println(task.get());// 获取返回值, get()
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class MyCallable implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("我Callable被调用了");
        TimeUnit.SECONDS.sleep(3);
        return "callable";
    }
}

运行结果如下:

在这里插入图片描述

两个线程运行,结果却只输出一次,这就是FutureTask的缓存作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值