总所周(java程序员)知,Runnable接口是没有返回值的,但是他的兄弟Callable有返回值。
贴代码吧。
/**
* 模拟Callable接口的future模式
*/
public class FutureModel {
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + ":start...");// 主线程开始
// 创建工作对象,相当于Callable变量
Task<String> task = new Task<String>() {
@Override
public String run() {
// 这里可以放置任何代码,比如网络请求,返回响应结果
System.out.println(Thread.currentThread().getName() + ":start...");// 子线程开始
try {
System.out.println(Thread.currentThread().getName() + ":work...");// 子线程工作
Thread.sleep(2000);// 模拟阻塞
int a = 1 / 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":done...");// 子线程结束
return "张5G";
}
};
// FuturePool相当于线程池,这里是提交任务返回Future对象
FutureData<String> futureData = FuturePool.submit(task);// 这里不会形成阻塞,主线程继续运行
System.out.println(Thread.currentThread().getName() + ":work...");// 主线程工作
String result = futureData.get();// 这里会阻塞调用线程,如主线程阻塞
System.out.println(Thread.currentThread().getName() + ":result:" + result);// 主线程获取到结果
System.out.println(Thread.currentThread().getName() + ":done...");// 主线程结束
}
}
/**
* 相当于Callable接口
*/
interface Task<T> {
T run();
}
/**
* 真正执行Task中的run方法
*/
class TaskData<T> {
Task<T> task;
T data;
volatile boolean isDone = false;
public TaskData(Task<T> task) {
this.task = task;
}
protected synchronized void doWork() {
try {
data = task.run();
} finally {
isDone = true;
notify();// 唤醒等待的线程
}
}
public synchronized T getFuture() throws InterruptedException {
while (!isDone) {
wait();// 如果没有执行完一直等待
}
return data;
}
}
/**
* 模拟线程池接收任务,委派线程去执行,所以不会阻塞调用线程
*/
class FuturePool {
public static <T> FutureData<T> submit(Task<T> task) {
FutureData<T> futureData = new FutureData<T>(task);
new Thread(new Runnable() {
@Override
public void run() {
futureData.taskData.doWork();
}
}).start();
return futureData;
}
}
class FutureData<T> {
TaskData<T> taskData;
public FutureData(Task<T> task) {
taskData = new TaskData<T>(task);
}
public T get() throws InterruptedException {
return taskData.getFuture();
}
}