精华内容
下载资源
问答
  • Java实现异步调用

    2021-03-03 09:53:23
    Java实现异步调用 一、创建线程 @Test public void test0() throws Exception { System.out.println("main函数开始执行"); Thread thread=new Thread(new Runnable() { @Override public void run() { ...

    Java实现异步调用

    一、创建线程

     @Test
    public void test0() throws Exception {
      System.out.println("main函数开始执行");
      Thread thread=new Thread(new Runnable() {
        @Override
        public void run() {
          System.out.println("===task start===");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println("===task finish===");
        }
      });
    
      thread.start();
      System.out.println("main函数执行结束");
    
    }
    

    二、Future

    jdk8之前的实现方式,在JUC下增加了Future,从字面意思理解就是未来的意思,但使用起来却着实有点鸡肋,并不能实现真正意义上的异步,获取结果时需要阻塞线程,或者不断轮询。

    @Test
    public void test1() throws Exception {
    
        System.out.println("main函数开始执行");
    
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<Integer> future = executor.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
    
                System.out.println("===task start===");
                Thread.sleep(5000);
                System.out.println("===task finish===");
                return 3;
            }
        });
        //这里需要返回值时会阻塞主线程,如果不需要返回值使用是OK的。倒也还能接收
        //Integer result=future.get();
        System.out.println("main函数执行结束");
    
        System.in.read();
    
    }
    

    三、CompletableFuture

    使用原生的CompletableFuture实现异步操作,加上对lambda的支持,可以说实现异步任务已经发挥到了极致。

     @Test
    public void test2() throws Exception {
        System.out.println("main函数开始执行");
        ExecutorService executor = Executors.newFixedThreadPool(2);
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                System.out.println("===task start===");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("===task finish===");
                return 3;
            }
        }, executor);
        future.thenAccept(e -> System.out.println(e));
        System.out.println("main函数执行结束");
    }
    

    四、Spring的Async注解

    使用spring实现异步需要开启注解,可以使用xml方式或者java config的方式。

    xml方式: <task:annotation-driven />

    <task:annotation-driven executor="executor" />
    <task:executor id="executor"
            pool-size="2" 线程池的大小
            queue-capacity="100" 排队队列长度 
            keep-alive="120" 线程保活时间(单位秒)
            rejection-policy="CALLER_RUNS" 对拒绝的任务处理策略 />
    

    java方式:

    @EnableAsync
    public class MyConfig {
    
        @Bean
        public TaskExecutor executor(){
            ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(10); //核心线程数
            executor.setMaxPoolSize(20);  //最大线程数
            executor.setQueueCapacity(1000); //队列大小
            executor.setKeepAliveSeconds(300); //线程最大空闲时间
            executor.setThreadNamePrefix("fsx-Executor-"); //指定用于新创建的线程名称的前缀。
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            return executor;
        }
    }
    

    (1)@Async

    @Test
    public void test3() throws Exception {
        System.out.println("main函数开始执行");
        myService.longtime();
        System.out.println("main函数执行结束");
    }
    
     @Async
    public void longtime() {
        System.out.println("我在执行一项耗时任务");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("完成");
    
    }
    

    (2)AsyncResult

    如果需要返回值,耗时方法返回值用AsyncResult包装。

    @Test
    public void test4() throws Exception {
        System.out.println("main函数开始执行");
        Future<Integer> future=myService.longtime2();
        System.out.println("main函数执行结束");
        System.out.println("异步执行结果:"+future.get());
    }
    
     @Async
    public Future<Integer> longtime2() {
        System.out.println("我在执行一项耗时任务");
    
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
        System.out.println("完成");
        return new AsyncResult<>(3);
    }
    展开全文
  • java实现异步调用

    万次阅读 2020-07-21 17:21:02
    1、使用线程池的逻辑实现异步调用 package com.ourlang.dataextract.controller; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.ourlang.dataextract.common.CommonResult; import ...

    1、使用线程池的逻辑实现异步调用

    package com.ourlang.dataextract.controller;
    
    import com.google.common.util.concurrent.ThreadFactoryBuilder;
    import com.ourlang.dataextract.common.CommonResult;
    import com.ourlang.dataextract.service.ISInPatientListService;
    import org.apache.tomcat.util.threads.ThreadPoolExecutor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 异步调用方法
     * <p>
     * https://github.com/ourlang
     * </p>
     *
     * @author ourlang
     */
    @RestController
    public class AsynCallController {
    
        private final ISInPatientListService inPatientListService;
    
        @Autowired
        public AsynCallController(ISInPatientListService inPatientListService) {
            this.inPatientListService = inPatientListService;
        }
    
        /**
         * 创建线程池 实现异步调用方法
         * @param serialNumber 住院号
         * @param itemIds      需要的导入的项目ID集合用逗号(`,`)隔开
         */
        private void createThead(String serialNumber, String itemIds) {
            ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
            ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
            //异步执行的方法
            singleThreadPool.execute(new PatientOtherData(serialNumber, itemIds));
            singleThreadPool.shutdown();
    
        }
    
        /**
         * 
         */
        private class PatientOtherData implements Runnable {
            private String serialNumber;
            private String itemIds;
    
            public PatientOtherData(String serialNumber, String itemIds) {
                this.serialNumber = serialNumber;
                this.itemIds = itemIds;
            }
    
            @Override
            public void run() {
                try {
                    //异步保存患者的其他数据
                    savePatientOtherData(serialNumber, itemIds);
                } catch (Exception e) {
                    System.out.println(e);
                }
    
            }
        }
    
    
        /**
         * 保存患者的所有信息到我们的mysql数据库
         * 保存患者主索引 (这张表暂时没有用)
         * isgPatientListService.savePrimaryIndexData();
         *
         * @param itemIds      选择导入患者的哪些数据
         * @param serialNumber 住院流水号
         */
        @RequestMapping("/savePatientDataById")
        public CommonResult savePatientDataById(@RequestParam(name = "SERIAL_NUMBER") String serialNumber, @RequestParam(name = "itemIds") String itemIds) {
            CommonResult commonResult = new CommonResult();
            commonResult.setCode(CommonResult.SUCCESS);
            commonResult.setMsg(CommonResult.SUCCESS_MESSAGE);
            //        1 2两点可以保证患者列表有数据
            //        1、保存患者就诊记录
            inPatientListService.saveInPatientList(serialNumber);
            System.out.println("serialNumber=" + serialNumber);
            System.out.println("itemIds=" + itemIds);
            //创建异步调用的线程池
            createThead(serialNumber, itemIds);
    
            return commonResult;
        }
    
    
        /**
         * 保存患者需要的其他数据
         *
         * @param itemIds 需要的导入的项目ID集合用逗号(`,`)隔开
         */
        public void savePatientOtherData(String serialNumber, String itemIds) throws Exception {
    
            Thread.sleep(5000);
            System.out.println("savePatientOtherData--serialNumber=" + serialNumber);
            System.out.println("savePatientOtherData--itemIds=" + itemIds);
    			//进行需要异步操作的一系列操作,比如存入数据库等等
        }
    }
    
    
    展开全文
  • Java 实现异步调用

    万次阅读 热门讨论 2018-04-03 15:27:12
    首先 我遇到的问题是 接口调用时需要更新缓存 而更新缓存又是个说快不快的过程 所以打算做异步调用 返回我所需要的结果即可 ,至于缓存什么时候更新完 就不是我所需要关注的了废话不多说 上代码public class ...

    首先 我遇到的问题是 接口调用时需要更新缓存 而更新缓存又是个说快不快的过程 所以打算做异步调用 返回我所需要的结果即可 ,至于缓存什么时候更新完 就不是我所需要关注的了

    废话不多说 上代码

    public class MyExecutor {

        private ExecutorService executor = Executors.newCachedThreadPool() ;

        public void fun() throws Exception {

            executor.submit(new Runnable(){

                @override

                    public void run() {

                        try {

                            //要执行的业务代码,我们这里没有写方法,可以让线程休息几秒进行测试

                            Thread.sleep(10000);

                            System.out.print("睡够啦~");

                        }catch(Exception e) {

                            throw new RuntimeException("报错啦!!");

                        }

                    }

            });

        }

    }

    public class Demo{

        

        public static void main(String[] args) {

            

             MyExecutor  myExecutor = new MyExecutor();

             try {

                myExecutor.fun();

                System.our.print("你先睡着,我先回家啦~");

            }catch(Exception e) {

                 throw new RuntimeException("业务程序报错啦!!");

            }

        }

    }

    好啦 代码到此结束 (ps:纯手打 若有错 请见谅) 

    运行主方法 

    会先打印(你先睡着,我先回家啦~)

    然后(睡够啦~)

    也就是说 在需要异步执行的方法未执行完毕时 主程序已经返回结果了  不需要继续等待 这样可以保证程序先返回结果 再继续执行不需要等待的繁琐的任务  当然也可以加一些方法去判断异步方法是否执行完毕。

    说一下Executors类

    这个类是用来创建线程池的

    有这么几个方法

    1、newFixedThreadPool() 创建固定大小的线程池 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程

    2、newCachedThreadPool() 创建一个可缓存的线程池,如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60s不执行任务)的线程,当任务数量增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于系统(JVM)能够创建的最大线程大小

    3、newSingleThreadExecutor() 创建一个单线程的线程池。这个线程池只有线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行

    4、newScheduledThreadPool() 创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求

    5、newSingleThreadScheduledExecutor() 创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求


    展开全文
  • 在java平台,实现异步调用的角色主要三种角色:调用者、取货凭证、真实数据。本篇文章给大家介绍java实现异步调用实例代码,需要的朋友可以参考下
  • java实现异步调用实例

    2019-04-25 17:25:34
    java实现异步调用实例
                    在JAVA平台,实现异步调用的角色有如下三个角色:
     
    调用者 取货凭证   真实数据
     
    一个调用者在调用耗时操作,不能立即返回数据时,先返回一个取货凭证.然后在过一断时间后凭取货凭证来获取真正的数据.
     

    所以连结调用者和真实数据之间的桥梁是取货凭证.我们先来看它的实现:

    public class FutureTicketprivate Object data = nullprivate boolean completed = false;  public synchronized void makeRealData()if(this.complited) return//获取数据的耗时操作.这里用Sleep代替  try{   Thread.sleep(10000);  }catch(Throwable t){}  this.data = "返回的数据内容"this.completed = true;  notifyAll(); }  public synchronized Object getData()while(!this.completed)){   try{    wait();   }catch(Throwable t){}  }  return this.data;   } public boolean isCompleted()return this.completed; }}

    为了简单化说明(不把它们的关系开得复杂),这里用Objectb代替了真实数据.而真实的实现中我们应该把makeData放在一个真实数据的类中,然后提供一个方法返回真实数据.这样对于真实数据的处理和取货凭证解耦.
     
    对于这个取货凭证,调用者的如何调用是异步调用的关键:

    publc class Requesterpublic FutureTicket request()final FutureTicket ft = new FutureTicket();    //在新线程中调用耗时操作  new Thread(){   public void run(){    ft.makeRealData();   }  }.start();  return ft; }}

    在新线程中启动耗时操作后,不等待线程的完成立即返回提货单.
     
    然后调用者可以根据ft.isCompleted()来调用getData()获取真实数据.当然对ft.isCompleted()测试可以按规定时间间隔轮巡(极低级的方案),也可以在条件不满足时wait(),然后等待makeData的notifyAll();这样你就完成了一个用JAVA模拟的异步操作.
     

    改进:
    但这样的调用对于调用者来说仍然要继续控制线程操作.如果调用者是一个资深的程序员,这当然没有问题.但假如我们把对直接数据的处理委托给取货凭证来做.调用者直接规定对数据的操作,然后由取货凭证来调用规定的操作,这对于调用者是一个很好的解脱:

    interface ProcessDatapublic void process(Onject data);} public MyProcessData{ public void process(Object data)//你不管什么时候起初数据data被获取了.  //你只要规定如果获取到数据了如何处理    System.out.println(data.toString() + "处理完成...........");  //insert into dataBase? }}

    取货凭证在接收调用者请求获取数据时,要知道对获取的数据如何处理的方法:

    public class FutureTicketprivate Object data = nullprivate boolean completed = falseprivate ProcessData pd;  public FutureTicket(ProcessData pd)this.pd = pd; } public synchronized void makeRealData(ProcessData pd)if(this.complited) return//获取数据的耗时操作.这里用Sleep代替  try{   Thread.sleep(10000);  }catch(Throwable t){}  this.data = "返回的数据内容"this.completed = true;  notifyAll(); }  public synchronized void putData()while(!this.completed)){   try{    wait();   }catch(Throwable t){}  }  //return this.data;  //不用返回了,直接处理  this.pd.process(this.data);  // alert(?);   }  //这个方法也可以不要了. public boolean isCompleted()return this.completed; }} 调用:   final FutureTicket ft = new FutureTicket(new ProcessData());    //在新线程中调用耗时操作  new Thread(){   public void run(){    ft.makeRealData();   }  }.start();  ft.putData();

    OK,你现在可以抽烟,喝酒,泡妞.ft会为你完成所有的工作.
               
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,719
精华内容 687
关键字:

java实现异步调用

java 订阅