您的位置:首页 > 其它

多线程--callable、Future、FutureTask

2016-12-18 13:19 239 查看
除了Runnable外,JAVA中还有callable、Future、FutureTask这几个线程。
与Runnable不同的是,他们只能运用到线程池中,而Runnable可以使用到Thread中。


一、Callable

他和Runnable功能大致相同,不同的是他有一个返回值。

他的声明如下:

public interface Callable<V> {
//返回V类型的结果
V call() throws Exception{}
}


二、Future

Runnable和Callable都无法对线程进行控制,一旦开始就无法进行管理。而Future可以执行cancel、isDone、get、set等方法。具体声明如下:

public interface Future<V> {
//取消线程
boolean cancel(boolean mayInterruptIfRunning);
//是否已经取消
boolean isCancelled;
//是否已经完成
boolean isDone();
//获取结果,若未完成则阻塞直到任务完成
V get() throws InterruptedException,ExecutionException;
//获取结果,若未完成则阻塞直到任务完成、或者超时。unit为时间单位
V get(long Timeout , TimeUnit unit) throws InterruptedException,ExecutionException,timeoutException;
}


get方法会阻塞直到任务完成,返回结果

三、FutureTask

它是Future接口的实现类,同时还实现了Runnable接口。

public class FutureTask<V> implements RunnableFuture<V> {
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;       // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW;       // ensure visibility of callable
}
}

public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}


可以看见FutureTask实现了 RunnableFuture,而 RunnableFuture继承了Runnable, Future;其中callable和Runnable通过构造函数注入,不过通过代码,我们可以知道注入的Runnable最后也转换为callable类型的任务。

由此可见,FutureTask实现了Runnable接口,可以通过Thread来直接运行,也可以提交到线程池,同时还能通get拿到结果。

现在通过一个DEMO来直观的展示他们之间的区别。

public class mFutureDemo {
//线程池
static ExecutorService mExecutor = Executors.newSingleThreadExecutor();
//主程序
public static void main(){

}

private static void runnable() throws ExecutionException, InterruptedException {
Future<?> result = mExecutor.submit(new Runnable() {
@Override
public void run() {
fibc(20);
}
});
System.out.print("runnable"+result.get());
}

private static void callable() throws ExecutionException, InterruptedException {
Future<Integer> result = mExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return fibc(20);
}
});
System.out.print("callable"+result.get());
}

private static void futureTask() throws ExecutionException, InterruptedException {
FutureTask<Integer> task=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return fibc(20);
}
});
mExecutor.submit(task);

//也可以和Runnable一样交给Thread来处理。
//Thread thread=new Thread(task);
//thread.start();

System.out.print("futureTask"+task.get());
}

//耗时操作
private static int fibc(int num){
if (num==0) return 0;
if (num==1) return 1;
return fibc(num-1)+fibc(num-2);
}
}


输出结果为:

runnable null;

callable 6765;

futureTask 6765;

上诉为非常简单的DEMO没有过多的注释,从中我们可以看出:

1、runnable是没有返回值的,callable和futureTask有返回值

2、runnable,callable是通过线程池返回的future来进行管理,无法自行管理;

而futureTask可以自行get返回值

3、其中get方法会阻塞,直到结果出来,才执行的打印语句。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: