java多线程之Callable和Future

Callable和Future一般是成对出现, 当我们获取线程执行结果时, 需要用到他们, Callable用于产生结果, Future用于获取结果.
Callable相当于计算产生结果部分, 而Future是获取计算产生结果的部分.


1.Callable

Callable是一个接口, 只包含call方法, 我们一般实现这个类, 然后在call方法中写自己的计算逻辑, 而方法返回值V是计算之后的结果.
这里写图片描述


2.Future .

Future也是一个接口, 用于获取异步计算结果. 提供了检查计算是否完成, 获取计算结果方法.
这里写图片描述


3.下面通过两种方式, 体会两者使用 .

Egg(相当于计算结果) :
这里写图片描述
EggCallable(相当于计算逻辑)
这里写图片描述

  1. 第一种方式
    这里写图片描述
    执行步骤 : 先创建一个EggCallable任务对象实现Callable, 在call方法中编写我们自己的计算逻辑. 并返回计算结果 . 然后创建一个线程池, 使用submit方法将任务提交上去, 之后立即返回Future对象, 这个对象可以查看计算是否完成, 可以获取完成之后的计算结果. 当异步计算没有产生结果之前, 会一直阻塞在get方法上, 直到有结果产生.

  2. 第二种方式
    这里写图片描述
    执行步骤 : 创建一个计算任务, 然后在创建一个futureTask对象, 将煮鸡蛋task传递. . 然后启动一个线程来执行futureTask任务 . 查看FutureTask后发现这个类实现Runnable接口, 相当于线程执行的任务, 是对我们自定义计算任务封装.


4. 分析源码.

首先, 我们必须知道FutureTask的继承关系方便后面理解:
这里写图片描述
查看AbstractExecutorService下对submit方法的实现 :
这里写图片描述
查看newTaskFor方法 :
这里写图片描述
对于execute方法相当于将任务添加到线程池中等待执行, 我们更应该关注FutureTask中的run方法,
我们观察run方法中, 其中”c.call()”就是在执行我们自定义的计算任务. set(result)相当于执行完毕之后, 将计算结果放在内存某个位置, 供get()方法进行获取 .
这里写图片描述
将计算结果赋值给outcome变量, finishCompletion应该是通知阻塞的get方法, 结果已经产生可以进行获取 . 有点生产者消费者意思, 在没有产品可消费情况下
消费者会进行阻塞, 直到生产者生产一个产品后, 会唤醒正在阻塞的消费者来消费产品.
这里写图片描述


5.自己实现一个类似功能的Future .

自己利用wait/notify形式, 实现一个自定义的Future .
MYCallable接口(相当于Callable功能) :

/**
 * Created by 张延 on 2017/5/19.
 */
public interface MYCallable<V> {
    V call()throws Exception ;
}

MyFuture接口 (相当于Future功能):

/**
 * Created by 张延 on 2017/5/19.
 */
public interface MYFuture<V> extends Runnable {
    V get() throws Exception;
}

MYExecutorService(相当于线程池角色) :

/**
 * Created by 张延 on 2017/5/19.
 */
public class MYExecutorService {

    public <T> MYFuture<T> submit(MYCallable<T> task) {
        if (task == null) throw new NullPointerException();
        MYFuture<T> future = newTaskFor(task);
        execute(future);
        return future;
    }

    public <T> MYFuture<T> newTaskFor(MYCallable<T> task) {
        return new MYFutureTask<T>(task);
    }

    public <T> void execute(MYFuture<T> future) {
        new Thread(future).start();
    }
}

MYFutureTask(相当于FutureTask功能) :

/**
 * Created by 张延 on 2017/5/19.
 */
public class MYFutureTask<T> implements MYFuture{

    private MYCallable<T> callable;
    private boolean isOk;
    public T result;

    public MYFutureTask(MYCallable<T> callable) {
        this.callable = callable;
        isOk = false;
    }

    public synchronized void setData(T t) {
        this.result = t;
        isOk = true;
        notify();
    }

    @Override
    public synchronized T get() throws Exception {
        while(!isOk) {
            wait();
        }
        return result;
    }

    @Override
    public void run() {
        MYCallable<T> c = callable;
        T t = null;
        if(c != null && !isOk) {
            try {
                t = c.call();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        setData(t);
    }
}

Client :

/**
 * Created by 张延 on 2017/5/19.
 */
public class Client {
    public static void main(String[] args) {
        MYCallable<String> callable = new MYCallable<String>() {
            @Override
            public String call() throws Exception {
                // 模拟计算, 耗费时间
                Thread.sleep(5000);
                return "i am ok!!!";
            }
        };
        MYExecutorService service = new MYExecutorService();
        MYFuture<String> future = service.submit(callable);
        try {
            String result = future.get();
            System.out.printf(result);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值