• 多线程之Future模式


      对于多线程,当A线程需要获得B线程的处理结果,而B线程处理业务需要很长时间,这时候A线程如果一直等待B线程的处理结果,线程A才能继续往下执行代码,这种方式在效率不是很好。所以,这种场景可以使用多线程的Future模式。

      Future模式,就是当A线程需要B线程的处理结果,启动B线程,然后A线程继续往下走,而不必一直等待B线程的结果,当A线程需要用到B线程的结果时候再去获取结果,如果B线程还没处理好业务逻辑,则A线程一直处于阻塞状态。直到B线程处理完成。下面总结一下Future模式的实现方式。

      首先客户端向服务器请求,但是这个资源的创建是非常耗时的,这种情况下,首先返回Client一个FutureSubject,以满足客户端的需求,同时,Future会通过另外一个Thread 去构造一个真正的资源,资源准备完毕之后,在给future一个通知。如果客户端急于获取这个真正的资源,那么就会阻塞客户端的其他所有线程,等待资源准备完毕。

      公共数据接口,FutureData和RealData都要实现

    public interface Data {
    
        public abstract String getConent();
    }
    public class FutureData implements Data{
    
        private RealData realData;
        
        private boolean isReady=false;
        
      //进行真实数据的装载
    public synchronized void setRealData(RealData realData){ if(isReady) return; isReady=true; this.realData=realData; notify(); } //如果业务还没处理完成,则进入阻塞状态 public synchronized String getConent() { while(!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
        //业务逻辑处理完成,直接返回真实结果
    return this.realData.getConent(); } }
    public class RealData implements Data{
    
        private String result;
        //真正处理业务逻辑的方法
        public RealData(String queryStr){
            System.out.println("这是一个很耗时的请求...");
            try {
                Thread.sleep(5000);
            } 
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("操作完毕,获取结果");
            result="查询结果";
        }
        
        public String getConent() {
    
            return result;
        }
    
    }
    public class FutureClient {
        //处理客户端的请求
        public Data request(final String queryStr){
        
    final FutureData futureDate =new FutureData();
         //开启一个新的线程去处理复杂的业务逻辑
    new Thread(new Runnable() { public void run() { RealData realData=new RealData(queryStr);
             //处理完成对数据进行装载 futureDate.setRealData(realData); } }).start();
         //返回给客户端
    return futureDate; } }
    public class TestFuture {
    
        public static void main(String[]args){
            FutureClient fc=new FutureClient();
            Data data=fc.request("查询条件..");
            System.out.println("请求发送成功!");
            System.out.println("做其他的事情...");
            String result = data.getConent();
            System.out.println(result);
            
        }
    }

      在JDK1.5 Concurrent 中,提供了这种Callable和Future。Callable产生结果,Future拿到结果。 代码如下:

    public class Task implements Callable<String> {
    
        public String call() throws Exception {
    
            Thread.sleep(5000);
            
            return "Hello Future";
        }
    }

      首先处理业务逻辑的类必须实现Callable接口,他与runable接口的区别是,runable接口重写的Run方法没有返回值,而Callable接口可以定义返回值。

    public class FutureDemo {
    
        public static void main(String[]args) throws InterruptedException, ExecutionException{
            
             System.out.println("已经提交资源申请");
             
             ExecutorService executor=Executors.newCachedThreadPool();
             
             Task task =new Task();
             
             Future<String> future=executor.submit(task);
             
             System.out.println("继续做其他事情...");
             
             if(!future.isDone()){
                 System.out.println("任务还没处理完成.."); 
             }
             System.out.println("获取返回结果:"+future.get());
             
             if(future.isDone()){
                 System.out.println("任务处理完成"); 
             }
             executor.shutdown();
        }
    }

      使用线程池 ExecutorService executor=Executors.newCachedThreadPool(),调用submit方法开启线程,submit方法与executor方法的区别是,submit可以传入实现Callable或者runable接口类型的参数,而executor只可以传入实现runable接口类型的参数。

  • 相关阅读:
    IBM MQ 学习
    spring中配置监听队列的MQ
    数据库优化(二)
    设计模式
    VBA学习笔记(2)--新建word文档并插入文字
    VBA代码分行
    excel保存时出现“请注意,您的文档的部分内容可能包含了文档检查器无法删除的个人信息”
    Excel VBA 操作 Word(入门篇)
    win10无法使用内置管理员账户打开应用
    五笔字根拆分规则_字根拆分方法
  • 原文地址:https://www.cnblogs.com/gdpuzxs/p/6753571.html
Copyright © 2020-2023  润新知