通过前面几篇的学习,我们知道创建线程的方式有两种,一种是实现Runnable接口,另一种是继承Thread,但是这两种方式都有个缺点,那就是在任务执行完成之后无法获取返回结果,那如果我们想要获取返回结果该如何实现呢?还记上一篇Executor框架结构中提到的Callable接口和Future接口吗?,是的,从JAVA SE 5.0开始引入了Callable和Future,通过它们构建的线程,在任务执行完成后就可以获取执行结果,今天我们就来聊聊线程创建的第三种方式,那就是实现Callable接口。
public interface Runnable {
public abstract void run();
}
而Callable的接口定义如下
public interface Callable {
V call() throws Exception;
}
该接口声明了一个名称为call()的方法,同时这个方法可以有返回值V,也可以抛出异常。嗯,对该接口我们先了解这么多就行,下面我们来说明如何使用,
前篇文章我们说过,无论是Runnable接口的实现类还是Callable接口的实现类,都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行,
ThreadPoolExecutor或ScheduledThreadPoolExecutor都实现了
ExcutorService接口,
而因此
Callable需要和Executor框架中的ExcutorService结合使用,我们先看看ExecutorService提供的方法:
Future submit(Callable task);
Future submit(Runnable task, T result);
Future> submit(Runnable task);
public static Callable
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;
}
public class FutureTask implements RunnableFuture {
FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:
public interface RunnableFuture extends Runnable, Future {
void run();
}
public FutureTask(Callable callable) {
}
public FutureTask(Runnable runnable, V result) {
}
package com.zejian.Executor;
import java.util.concurrent.Callable;
/**
* @author zejian
* @time 2016年3月15日 下午2:02:42
* @decrition Callable接口实例
*/
public class CallableDemo implements Callable {
private int sum;
@Override
public Integer call() throws Exception {
System.out.println("Callable子线程开始计算啦!");
Thread.sleep(2000);
for(int i=0 ;i<5000;i++){
sum=sum+i;
}
System.out.println("Callable子线程计算结束!");
return sum;
}
}
Callable执行测试类如下:
package com.zejian.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @author zejian
* @time 2016年3月15日 下午2:05:43
* @decrition callable执行测试类
*/
public class CallableTest {
public static void main(String[] args) {
//创建线程池
ExecutorService es = Executors.newSingleThreadExecutor();
//创建Callable对象任务
CallableDemo calTask=new CallableDemo();
//提交任务并获取执行结果
Future future =es.submit(calTask);
//关闭线程池
es.shutdown();
try {
Thread.sleep(2000);
System.out.println("主线程在执行其他任务");
if(future.get()!=null){
//输出获取到的结果
System.out.println("future.get()-->"+future.get());
}else{
//输出获取到的结果
System.out.println("future.get()未获取到结果");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程在执行完成");
}
}
Callable子线程开始计算啦!
主线程在执行其他任务
Callable子线程计算结束!
future.get()-->12497500
主线程在执行完成
|
package com.zejian.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* @author zejian
* @time 2016年3月15日 下午2:05:43
* @decrition callable执行测试类
*/
public class CallableTest {
public static void main(String[] args) {
// //创建线程池
// ExecutorService es = Executors.newSingleThreadExecutor();
// //创建Callable对象任务
// CallableDemo calTask=new CallableDemo();
// //提交任务并获取执行结果
// Future future =es.submit(calTask);
// //关闭线程池
// es.shutdown();
//创建线程池
ExecutorService es = Executors.newSingleThreadExecutor();
//创建Callable对象任务
CallableDemo calTask=new CallableDemo();
//创建FutureTask
FutureTask futureTask=new FutureTask<>(calTask);
//执行任务
es.submit(futureTask);
//关闭线程池
es.shutdown();
try {
Thread.sleep(2000);
System.out.println("主线程在执行其他任务");
if(futureTask.get()!=null){
//输出获取到的结果
System.out.println("futureTask.get()-->"+futureTask.get());
}else{
//输出获取到的结果
System.out.println("futureTask.get()未获取到结果");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程在执行完成");
}
}
Callable子线程开始计算啦!
主线程在执行其他任务
Callable子线程计算结束!
futureTask.get()-->12497500
主线程在执行完成
|