Java中的Runnable,Callable,Future,FutureTask的比较
Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。
Runnable
其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中, 该函数没有返回值 。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。Runnable的声明如下 :
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Callable
Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是 call()函数有返回值 ,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :
@FunctionalInterface public interface Callable{ V call() throws Exception; }
可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。
Future
Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。Future声明如下:
* @see FutureTask * @see Executor * @since 1.5 * @author Doug Lea * @paramThe result type returned by this Future's {@code get} method */ public interface Future { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
FutureTask
FutureTask则是一个RunnableFuture< V>,而RunnableFuture实现了Runnbale又实现了Futrue< V>这两个接口:
public class FutureTaskimplements RunnableFuture { ...... }
RunnableFuture
public interface RunnableFutureextends Runnable, Future { void run(); }
另外FutureTask还可以包装Runnable和Callable< V>, 由构造函数注入依赖。
public FutureTask(Callablecallable) { 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 }
可以看到,Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务。该适配函数的实现如下 :
public staticCallable callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter (task, result); }
RunnableAdapter适配器
static final class RunnableAdapterimplements Callable { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }
由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。
因此FutureTask既是Future、Runnable,又是包装了Callable(如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。
完整示例:
package com.stay4it.rx;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class FutureTest {
public static class Task implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run");
}
}
public static class Task2 implements Callable {
@Override
public Integer call() throws Exception {
System.out.println("call");
return fibc(30);
}
}
public static void testRunnable(){
ExecutorService executorService = Executors.newCachedThreadPool();
Future future = (Future) executorService.submit(new Task());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executorService.shutdown();
}
public static void testCallable(){
ExecutorService executorService = Executors.newCachedThreadPool();
Future future = (Future) executorService.submit(new Task2());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executorService.shutdown();
}
public static void testFutureTask(){
ExecutorService executorService = Executors.newCachedThreadPool();
FutureTask futureTask = new FutureTask(new Task2());
executorService.submit(futureTask);
try {
System.out.println(futureTask.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executorService.shutdown();
}
public static void testFutureTask2(){
ExecutorService executorService = Executors.newCachedThreadPool();
FutureTask futureTask = new FutureTask(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("testFutureTask2 run");
}
},fibc(30));
executorService.submit(futureTask);
try {
System.out.println(futureTask.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executorService.shutdown();
}
public static void main(String[] args) {
testCallable();
}
static int fibc(int num) {
if (num == 0) {
return 0;
}
if (num == 1) {
return 1;
}
return fibc(num - 1) + fibc(num - 2);
}
}
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!



