前言,在java线程中最常见的是Thread 和Runnable,很少见到或者用到callable等类。但是,你接触过android源码就会经常看到这些类,比如AsyncTask的源码在execute方法源码可以看到了这些类。在面试时也有可能会问到两者的区别,所以现在容许鄙人来介绍一下java中这些类的用法。
Runnable
Runnable一个接口类,包括一个run的接口方法:通常我们会自定义一个类去实现Runnable,这时候还可以实现其他接口方法,如果类要是继承Thread就不能再继承其他类了。
public interface Runnable{
public abstract void run();
}
Runnable 通常配合Thread使用,在run方法里面写耗时的操作:
new Thread(new Runnable(){
public void run(){
//
}
}).start();
Callable
Callable是一个泛型接口,要比Runnable强些 ,因为接口方法call有返回值,并且返回值是传入的泛型类型,还能call的过程中抛出异常。
public interface Callable<V>{
V call() throws Exception;
}
示例要配合Future或者FutureTask来执行。
Future
Future是一个泛型接口类,是Runnable和Callable的调度容器,就是对Runnable和Callable的结果进行操作,比如:
- isCancelled()取消操作,call方法任务完成前取消,返回true。
- isDone()判断是否操作完成,是则返回true。
- get()获取操作结果,会导致程序阻塞,必须等到子线程结束才会得到返回值。
- get(long timeout TimeUnit unit)在某时间后获取操作结果,如果在规定时间内获取不到返回值将会抛出超时异常)
public interface Future<V>{
boolean isCancelled();
boolean isDone();
V get() throws InterputeredException,ExecutionExeception;
V get(long timeout ,TimeUnit unit)throws InterputeredException,ExecutionExeception,TimeoutExeception;
}
比如
ExecutorService threadPool=Executors.newSingleThreadExecutor();
Future future=threadPool.submit(new Callable<String>(){
public String call()throws Exception{
return "result";
}
});
Futurn.get();//返回操作结果
FutureTask
FutureTask类同时实现了Runnable和Future<V> 两个接口,具有了两个接口的属性。
public class FutureTask<V> implements RunnableFuture<V>{
public FutureTask(Callable<V> callable){
this.callable=callable;
...
}
public FutureTask(Runnable runnable,V result){
this.callable=Executors.callable(runnable,result);
...
}
boolean isCancelled();
boolean isDone();
V get() throws InterputeredException,ExecutionExeception;
V get(long timeout ,TimeUnit unit)throws InterputeredException,ExecutionExeception,TimeoutExeception;
}
public interface RunnableFuture<V> implements Runnable,Future<V>{
void run();
}
这里的FutureTask间接实现了两个接口,在FutureTask的构造方法传入Callable或者是Runnable,而Runnable会转为Callable,runnable通过runnableadapter转为callable。同时FutureTask还具备Future的所有方法。
举个例子
Callable<Integer> callable=new Callable<Integer>(){
public Ingeter call() throws Exception{
return 100;
}
};
FutureTask<Integer> task=new FutureTask<Integer>(callable);
new Thread(task).start();
task.get();//当然要先启动线程才能得到结果;
这里的callable当成runnable用了。
总结
-
Callable比Runnable高级能返回结果值和抛出异常
-
可以有上述例子看到Callable来产生结果,Futuretask来获取结果。
-
在获取结果期间还可以控制是否取消thread 判断thread是否完成。
-
FutureTask调用get方法获取call返回值过程中,主线程会阻塞,直到call方法结束并且返回。
网友评论