一般使用线程有两种方式:继承Thread类重写run方法;另一种就是实现Runnable接口,实现run方法。但是run方法没有返回值,假如我们在使用线程的时候想要知道运行结果,就只能使用重写run方法,并且使用回调来得到运行结果。但是我们Callable接口的call方法,可以返回执行结果。如下:
public interface Runnable
{
public abstract void run();
}
public interface Callable
{
public abstract Object call()
throws Exception;
}
Future: 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用
get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用
Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。
public abstract boolean <code><strong><a target=_blank href="">cancel</a></strong>(boolean mayInterruptIfRunning)</code> ;
cancel用来取消任务,取消成功返回true,取消失败返回false。mayInterruptIfRunning表示正在执行但还没执行完的任务是否可以取消。如果任务已完成、或已取消。那么不管mayInterruptIfRunning是ture还是false,方法执行返回false。如果任务在执行中,那么若mayInterruptIfRunning为ture那么返回true;若mayInterruptIfRunning为false,结果返回false。如果任务还没执行,不管mayInterruptIfRunning是ture还是false,方法返回true。
public abstract Object get()
throws InterruptedException, ExecutionException;
get方法用来获取线程执行返回结果。这个方法回阻塞,知道返回结果。 public abstract boolean isCancelled();
如果在任务正常完成前将其取消,则返回 true。get(long timeout, TimeUnit unit)
如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。public abstract boolean isDone();
如果任务已完成,则返回 true。
FutureTask:可取消的异步计算。利用开始和取消计算的方法、查询计算是否完成的方法和获取计算结果的方法,此类提供了对
Future
的基本实现。仅在计算完成时才能获取结果;如果计算尚未完成,则阻塞
get 方法。一旦计算完成,就不能再重新开始或取消计算。
Callable:Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。 Callable
接口只有一个call方法,如下:
public abstract Object call()
throws Exception;
因为Executor接口只提供了一个方法,参数中只能接受Runnable类型,如下:
public abstract void execute(Runnable runnable);
因此,Callable只能与ExecutorService一起使用。因为ExecutorService提供了可接受Callable类型的参数。如下: public abstract Future submit(Callable callable);
public abstract Future submit(Runnable runnable, Object obj);
public abstract Future submit(Runnable runnable);
下面来看使用示例:
示例1:使用Callable和Future,并且输出线程计算返回值
public class Test3 {
public static void main(String[] args) {
ExecutorService executor=Executors.newCachedThreadPool();
Future<Integer> future=executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 1000; i++) {
sum+=i;
}
return sum;
}
});
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();
}
}
}
输出结果:
线程执行结果:500500
示例2:使用Callable和FutureTask,并且输出线程计算返回值
public class CallableFutureTask {
public static void main(String[] args) {
ExecutorService executor=Executors.newCachedThreadPool();
FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 1000; i++) {
sum+=i;
}
return sum;
}
});
executor.submit(futureTask);
executor.shutdown();
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();
}
}
}
示例3:使用使用Callable和FutureTask,并且输出线程计算返回值。用启动普通线程来执行public class CallableFutureTaskThread {
public static void main(String[] args) {
FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 1000; i++) {
sum+=i;
}
return sum;
}
});
Thread thread=new Thread(futureTask);
thread.start();
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();
}
}
}