一、模式讲解
Main:系统启动,调用Client发出请求
Client:返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData
Data:返回数据的接口
FutureData:Futrue数据,是一个虚拟的数据,需要装配RealData
RealData:真实数据,构造比较慢。
二、模式案例
1、Data数据接口
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:10
* @Description:
*/
public interface Data {
String getData();
}
2、RealData实现
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:10
* @Description:
*/
public class RealData implements Data {
private String data;
public RealData(String data) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data;
}
@Override
public String getData() {
System.out.println("做大量业务");
return this.data+"业务数据";
}
}
3、FutureData虚拟数据实现,需要装配真实数据
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:10
* @Description:
*/
public class FutureData implements Data {
private RealData realData=null;
private boolean ready=false;
public synchronized void setRealData(RealData realData){
if(ready){
return;
}
this.realData=realData;
this.ready=true;
notifyAll();
}
@Override
public synchronized String getData() {
while (!ready){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realData.getData();
}
}
4、Client客户端,返回虚拟数据,调用真实数据,若没有调用完,则等待
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:07
* @Description:
*/
public class Client {
public Data request(String request){
System.out.println("开始请求");
final FutureData futureData=new FutureData();
new Thread(){
@Override
public void run() {
super.run();
RealData realData=new RealData(request);
futureData.setRealData(realData);
}
}.start();
return futureData;
}
}
5、Mian 测试类
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:36
* @Description:
*/
public class TestMain {
public static void main(String[] str){
System.out.println("开始");
Client client=new Client();
Data data = client.request("ming");
System.out.println("主线程业务");
System.out.println(data.getData());
}
}
三、jdk内置实现
摘取网上例子
因为该例子设计到线程池,下面简单介绍一下线程池:
Java通过Executors提供四种线程池
1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
在多线程的开发中往往会遇到这种情况:主线程需要知道子线程的运行结果,以便确定如何执行任务.JDK1.5以后就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
步骤:
1)任务类实现Callable接口
2)创建线程池:ExecutorService es = Executors.newCachedThreadPool();
3)执行任务:chuju cj = new chuju();Future future = es.submit(cj);
4)获取子线程中任务的执行结果:future.get()
小例子场景
假如你想做饭,但是没有厨具,也没有食材。网上购买厨具比较方便,食材去超市买更放心,即买出具、买食材,这两个任务异步执行,买好后才能去做饭。
代码实现:
1、厨具
**
* @Auther: chenhm
* @Date: 2019/7/30 11:49
* @Description:
*/
public class Chuju implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("买厨具");
Thread.sleep(2000);
System.out.println("买好厨具");
return true;
}
}
2、食材
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:51
* @Description:
*/
public class Shicai implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("买食材");
Thread.sleep(2100);
System.out.println("买好食材");
return true;
}
}
3、做饭
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:53
* @Description:
*/
public class Zuofan implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("做饭");
Thread.sleep(2300);
System.out.println("做好饭");
return true;
}
}
4、测试类
/**
* @Auther: chenhm
* @Date: 2019/7/30 11:54
* @Description:
*/
public class TestMain {
public static void main(String[] str){
try {
long start=System.currentTimeMillis();
ExecutorService service= Executors.newFixedThreadPool(3);
Chuju chuju=new Chuju();
Shicai shicai=new Shicai();
Zuofan zuofan=new Zuofan();
Future<Boolean> submit = service.submit(chuju);
Future<Boolean> submit1 = service.submit(shicai);
Boolean b=submit.get();
Boolean b1=submit1.get();
if(b&&b1){
service.submit(zuofan);
}
service.shutdown();
System.out.println("耗时="+(System.currentTimeMillis()-start));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
参考文章:
https://segmentfault.com/a/1190000015558810
https://www.cnblogs.com/myxcf/p/9959870.html