Future设计模式是Java多线程开发常用设计模式。
一句话,将客户端请求的处理过程从同步改为异步,以便将客户端解放出来,
在服务端程序处理期间可以去干点其他事情,最后再来取请求的结果。
好处在于整个调用过程中不需要等待,可以充分利用所有的时间片段,提高系统的响应速度。
接口定义
package com.zl.step19;
/**
* 获取计算呢结果和判断任务是否完成两个接口
* @param <T>
*/
public interface Future<T> {
// 返回计算后的结果,该方法会陷入阻塞状态
T get() throws InterruptedException ;
// 判断任务是否已经被完成
boolean done();
}
package com.zl.step19;
public interface Task<IN,OUT> {
// 给定一个参数,经过计算返回结果
OUT get(IN input);
}
package com.zl.step19;
import java.util.concurrent.Callable;
public interface FutureService<IN,OUT> {
// 接受不需要返回值的任务
Future<?> submit(Runnable runnable);
// 提交需要返回值的任务
Future<OUT> submit(Task<IN,OUT> task, IN input);
// 提交需要返回值的任务 回调函数
Future<OUT> submit(Task<IN,OUT> task, IN input, Callback<OUT> callback);
// 使用静态方法构建一个FutureService
static <T,R> FutureService<T,R> newService(){
return new FutureServiceImpl<>();
}
}
package com.zl.step19;
public interface Callback<T> {
//任务完成后会调用该方法, 其中T为任务执行后的结果
void call(T t);
}
程序实现
package com.zl.step19;
public class FutureTask<T> implements Future<T> {
// 计算结果
private T result ;
// 是否已经完成
private boolean isDone = false ;
// 定义对象锁
private final Object LOCK = new Object() ;
@Override
public T get() throws InterruptedException {
synchronized (LOCK) {
// 当任务还没有完成时,调用get方法被挂起,进入阻塞
while (!isDone) {
LOCK.wait();
}
}
// 计算返回结果
return result;
}
// 设置计算结果
protected void finish(T result){
synchronized (LOCK) {
if(isDone){
return;
}
this.result = result ;
this.isDone = true;
LOCK.notifyAll();
}
}
@Override
public boolean done() {
return isDone;
}
}
package com.zl.step19;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* 当提交任务的时候,创建一个信息的线程来受理该任务,进而达到任务异步执行的效果
* @param <IN>
* @param <OUT>
*/
public class FutureServiceImpl<IN,OUT> implements FutureService<IN,OUT> {
// 为执行的线程指定名字前缀
private final static String FUTURE_THREAD_PREFIX = "FUTURE-" ;
private final AtomicInteger nextCounter = new AtomicInteger(0) ;
private String getNextName(){
return FUTURE_THREAD_PREFIX+nextCounter.getAndIncrement() ;
}
@Override
public Future<?> submit(Runnable runnable) {
final FutureTask<Void> future = new FutureTask<>();
new Thread(()->{
runnable.run();
future.finish(null);
},getNextName()).start();
return future;
}
@Override
public Future<OUT> submit(Task<IN, OUT> task, IN input) {
final FutureTask<OUT> future = new FutureTask<>();
new Thread(()->{
OUT result = task.get(input) ;
// 设置返回结果
future.finish(result);
},getNextName()).start();
return future;
}
@Override
public Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback) {
final FutureTask<OUT> future = new FutureTask<>();
new Thread(()->{
OUT result = task.get(input) ;
// 设置返回结果
future.finish(result);
if(null != callback){
// 回调函数
callback.call(result);
}
},getNextName()).start();
return future;
}
}
使用&总结
package com.zl.step19;
import java.util.concurrent.TimeUnit;
// 提交无返回值的任务
public class FutureTest01 {
public static void main(String[] args) throws InterruptedException {
FutureService<Void,Void> service = FutureService.newService();
Future<?> future = service.submit(()-> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am finish done .");
});
//get 方法 会使当前线程进入
future.get();
}
}
package com.zl.step19;
import java.util.concurrent.TimeUnit;
// 提交有返回值的任务
public class FutureTest02 {
public static void main(String[] args) throws InterruptedException {
FutureService<String,Integer> service = FutureService.newService();
Future<Integer> future = service.submit(input-> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return input.length();
},"Hello");
//get 方法 会使当前线程进入
future.get();
}
}
package com.zl.step19;
import java.util.concurrent.TimeUnit;
// 提交有返回值的任务 支持回调函数
public class FutureTest03 {
public static void main(String[] args) throws InterruptedException {
FutureService<String,Integer> service = FutureService.newService();
Future<Integer> future = service.submit(input-> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return input.length();
},"Hello",System.out::println);
//get 方法 会使当前线程进入
future.get();
}
}