一、Callable vs Runnable
(1)Callable接口有返回值,Runnable接口无返回值;
(2)Callable接口会抛异常,Runnable接口不会抛异常;
(3)落地方法不一样,Callable是call,Runnable是run;
二、怎么用
2.1、直接替换Runnable是否可行
不可行。因为Thread类的构造方法根本没有Callable。
2.2、适用场景
这像认识一个不认识的同学,我可以找中间人介绍。
三、FutureTask
3.1、概述
未来的任务,用它干一件事,异步调用。main方法就像一个糖葫芦,一个个方法由main串起来。
问题:解决不了正常调用挂起引起的堵塞问题。
案例:
(1)老师上着课,口渴了,去买水不合适,讲课线程继续,我可以单起个线程找班长帮忙买水,水买回来了放桌上,我需要的时候再去get;
(2)4个同学,A计算1+20、B计算21+30、C计算31*到40、D计算41+50,是不是C的计算量有点大啊,FutureTask单起个线程给C计算,我先汇总ABD,最后等C计算完了再汇总
C,拿到最终结果;
(3)高考:会做的先做,不会的放在后面做;
3.2、原理
在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些任务交给FutureTask对象在后台完成,当主线程将来需要时,就可以通过FutureTask对象获得后台作业的计算结果或者执行状态。一般FutureTask对象多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。
只计算一次get方法放到最后。
3.3、案例代码
3.3.1、CallableThread
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 16:27
 * @Description: 王五计算21*22*23*...*25
 */
public class CallableThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 1;
        for (int i = 21; i <= 25; i++) {
            sum *= i;
        }
        Thread.sleep(1);
        return sum;
    }
}3.3.2、CallableMainApp
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 16:01
 * @Description:
 * 需求描述:
 *      三个同学安排任务如下:
 *          (1)张三计算 1+2+3+...+10
 *          (2)李四计算 11+12+13+...+20
 *          (3)王五计算 21*22*23*...*25
 *      把三个人的计算结果求和,求出总结果
 */
public class CallableMainApp {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> wangwuFutureTask = new FutureTask<>(new CallableThread());
        AtomicReference<Integer> zhangsanSumResult = new AtomicReference<>(0);
        AtomicReference<Integer> lisiSumResult = new AtomicReference<>(0);
        /**
         * 张三计算 1+2+3+...+10
         */
        new Thread(() -> {
            try {
                int zhangsanSum = 0;
                for (int i = 1; i <= 10; i++) {
                    zhangsanSum += i;
                }
                zhangsanSumResult.set(zhangsanSum);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "zhangsan").start();
        /**
         * 李四计算 11+12+13+...+20
         */
        new Thread(() -> {
            try {
                int lisiSum = 0;
                for (int i = 11; i <= 20; i++) {
                    lisiSum += i;
                }
                lisiSumResult.set(lisiSum);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "lisi").start();
        /**
         * 王五计算 21*22*23*...*25
         */
        new Thread(wangwuFutureTask, "wangwu").start();
        System.out.println("zhangsanResult = " + zhangsanSumResult.get());
        System.out.println("lisiResult = " + lisiSumResult.get());
        while (!wangwuFutureTask.isDone()) {
            System.out.println("=====================>王五拼命计算中");
        }
        Integer wangwuResult = wangwuFutureTask.get();
        System.out.println("wangwuResult = " + wangwuResult);
        Integer sum = zhangsanSumResult.get() + lisiSumResult.get() + wangwuResult;
        System.out.println("sum = " + sum);
    }
} 














![sql注入 [极客大挑战 2019]HardSQL1](https://img-blog.csdnimg.cn/4d2eb3b71a5144d4912d593d0d1e3844.png)

![集成多元算法,打造高效字面文本相似度计算与匹配搜索解决方案,助力文本匹配冷启动[BM25、词向量、SimHash、Tfidf、SequenceMatcher]](https://img-blog.csdnimg.cn/d553c7dadca54bdb82a3a234befb74d8.png#pic_center)


