6、Callable接口的使用(简单)

引用学习(狂神说)

使用解析

1、首先查看官方文档和源码是如何讲解的

 

可以知道以下几点:

1、Callable接口类似于Runnable接口

2、Callable有返回值

3、Callable可以抛出异常

4、调用call()方法

5、Callable支持泛型

2、既然和Runnable接口类似,就直接创建一下

class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("call()");
        return "123";
    }

}

3、重点:如何启动呢?

要知道线程的启动只能通过 new Thread().start()

  • Thread的构造方法中,只能丢入Runnable接口

那该怎么办?

现在知道的是Thread类,和Runnable接口有关系,我们是否可以通过Runnable接口和Thread类挂上关系呢?

通过图解拆分关系

  • 现在你是Callable接口,Runnable接口是的女朋友,Thread类是你女朋友的闺蜜

  • 而现在你想认识你女朋友的闺蜜,怎么办呢?

  • 如果你直接去找你女朋友的闺蜜,肯定会有些突兀或者造成误会!

  • 肯定需要通过你女朋友的介绍,对吧!

  • 那么你的女朋友要如何介绍呢?这是一个问题!

4、查看Runnable接口在文档中的说明

Runnable接口本身没有说明好看的,只是一个函数式接口,里面有个run()方法,仅此而已!

但是它有两个重要的实现类,图中已经标出:

点开实现类FutureTask

往下翻,在构造器中你会发现可以丢入一个Callable接口

 那么现在就可以通过FutureTask实现类和Thread类挂上关系了!

具体使用

有两个坑,需要注意返回参数和缓存

创建Callable线程并启动

package com.zxh.callable;

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

public class CallableTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);   // 适配器类

        new Thread(futureTask).start();
    }
}
class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("call()");
        return "123";
    }

}

Callable返回的参数和注意点

获取返回的参数

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

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);   // 适配器类

        new Thread(futureTask).start();

        Object o = futureTask.get();
        System.out.println(o);
    }
}
class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("call()");
        return "123";
    }

}

注意点

futureTask.get()方法可能会阻塞

因为call()中可能会存在耗时的任务,所以在获取返回值的时候,就会等待(阻塞)。

一般将get()方法放在最后一行,并用通过异步操作调用。

缓存

  • 当你使用两个线程调用的时候,会发现输出只有1次。

  • 因为结果被缓存,提高了效率

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

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);   // 适配器类

        new Thread(futureTask, "A").start();
        new Thread(futureTask, "B").start();    //结果会被缓存

        Object o = futureTask.get();    // 会阻塞,一般通过异步操作
        System.out.println(o);
    }
}
class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("call()");
        return "123";
    }

}

posted @ 2020-05-25 10:32  忘忧山的兰木  阅读(1889)  评论(0编辑  收藏  举报
她只是想吃这个而已啊……这一定是她非常爱吃的,我居然连如此细微的幸福也夺走了……
Hide
Switch
Save