JUC并发编程学习(七)-Callable学习

Callable

线程的创建方式主要有Thread、Runnable、Callable这几种,那么他们的主要区别是:

1.是否返回值?
Runnable无返回值,而Callable有返回值。
2.是否跑出异常?
Runnable无异常,Callable有异常
3.方法不同?
Runnable 运行的方法是run,Callable运行的方法是call

为了学习Callable,首先我们来写一个简单的线程,代码如下:

package com.jp.call;

import java.util.concurrent.Callable;

/**
 * @className:
 * @PackageName: com.jp.call
 * @author: youjp
 * @create: 2020-05-13 21:01
 * @description:   TODO 学习Callable
 * @Version: 1.0
 */
public class TestCallable {
    public static void main(String[] args) {
			//需要思考的地方
            new Thread(new Runnable() {
                @Override
                public void run() {
				
                }
            }).start();
    }
}

//自定义线程
class Mythread implements Callable{

    @Override
    public Object call() throws Exception {
        System.out.println("我是小Call我被调用了");
        return "小call";
    }
}

编写了一个有返回值的线程,但是我们要如何调用得到它呢?平时我们的线程大致的调用方法都是这种类型的:
在这里插入图片描述

Thread与Callable之间的适配类:FutureTask

查看官方API文档里Thread的相关构造方法发现,Thread创建线程,只能与Runnable有联系,与Callable没有直接关系。
在这里插入图片描述
Thread怎么创建Callable线程呢?

在设计模式中建立两者之间的关系经常使用适配器。什么是适配器呢?
适配器就是接口转换器。把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

我们去查找jdk官方文档,看能否找到Thread和Callable相互之间有关联的类。

1.查看Runnable官方文档
在这里插入图片描述
2.查看Runnable的子类FutureTask
在这里插入图片描述
可以看到通过FutureTask类我们找到了Thread与Callable之间联系了。
在这里插入图片描述

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

那么怎么使用呢?

package com.jp.call;

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

/**
 * @className:
 * @PackageName: com.jp.call
 * @author: youjp
 * @create: 2020-05-13 21:01
 * @description:   TODO 学习Callable
 * @Version: 1.0
 */
public class TestCallable {

    public static void main(String[] args) {

        //适配类
        FutureTask futureTask=new FutureTask(new Mythread());
        //执行线程
        new Thread(futureTask).start();

        try {
            //获取返回值
            System.out.println("获取到返回值:"+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

//自定义线程
class Mythread implements Callable{

    @Override
    public Object call() throws Exception {
        System.out.println("我是小Call我被调用了");
        return "小call";
    }
}

在这里插入图片描述

Callable有什么优点

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

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

package com.jp.call;

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

/**
 * @className:
 * @PackageName: com.jp.call
 * @author: youjp
 * @create: 2020-05-13 21:01
 * @description:   TODO 学习Callable
 * @Version: 1.0
 */
public class TestCallable {

    public static void main(String[] args) {

        //适配类
        FutureTask futureTask=new FutureTask(new Mythread());
        //执行线程
        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start();

        try {
            //获取返回值
            System.out.println("获取到返回值:"+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

//自定义线程
class Mythread implements Callable{

    @Override
    public Object call() throws Exception {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("我是小Call我被调用了");
        return "小call";
    }
}

运行结果如下:在这里插入图片描述

有兴趣的老爷,可以关注我的公众号【一起收破烂】,回复【006】获取2021最新java面试资料以及简历模型120套哦~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

收破烂的小熊猫~

你的鼓励将是我创造最大的东西~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值