java多线程之Callable和Future
Callable和Future一般是成对出现, 当我们获取线程执行结果时, 需要用到他们, Callable用于产生结果, Future用于获取结果.
Callable相当于计算产生结果部分, 而Future是获取计算产生结果的部分.
1.Callable
Callable是一个接口, 只包含call方法, 我们一般实现这个类, 然后在call方法中写自己的计算逻辑, 而方法返回值V是计算之后的结果.
2.Future .
Future也是一个接口, 用于获取异步计算结果. 提供了检查计算是否完成, 获取计算结果方法.
3.下面通过两种方式, 体会两者使用 .
Egg(相当于计算结果) :
EggCallable(相当于计算逻辑)
第一种方式
执行步骤 : 先创建一个EggCallable任务对象实现Callable, 在call方法中编写我们自己的计算逻辑. 并返回计算结果 . 然后创建一个线程池, 使用submit方法将任务提交上去, 之后立即返回Future对象, 这个对象可以查看计算是否完成, 可以获取完成之后的计算结果. 当异步计算没有产生结果之前, 会一直阻塞在get方法上, 直到有结果产生.第二种方式
执行步骤 : 创建一个计算任务, 然后在创建一个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();
}
}
}
上一篇: php图片增加中文与图片水印代码
下一篇: JavaScript 中的事件循环