java线程理解Future模式

一、模式讲解

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值