国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java實(shí)現(xiàn)異步的幾種方式

這篇具有很好參考價(jià)值的文章主要介紹了Java實(shí)現(xiàn)異步的幾種方式。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

  1. 普通線程實(shí)現(xiàn)異步,但頻繁創(chuàng)建、銷毀線程比較耗資源,所以一般交給線程池執(zhí)行
    //創(chuàng)建需要異步執(zhí)行的邏輯
    public class AsyncThread implements Runnable{
        @Override
        public void run() {
            System.out.println("異步線程開始");
            long start = System.currentTimeMillis();
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            long end = System.currentTimeMillis();
            System.out.println("異步線程:" + Thread.currentThread().getName() + "結(jié)束,耗時(shí):" + (end - start));
        }
    }
    
    //在業(yè)務(wù)中進(jìn)行調(diào)用
    @GetMapping("/thread")
    public String asyncThread(){
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 3, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.AbortPolicy());
        long start = System.currentTimeMillis();
        //自己的業(yè)務(wù)代碼。。。
        AsyncThread asyncThread = new AsyncThread();
        threadPool.execute(asyncThread);
        long end = System.currentTimeMillis();
        return "返回,耗時(shí):" + (end - start);
    }
    

    結(jié)果:Java實(shí)現(xiàn)異步的幾種方式

  2. Future異步

    和普通線程實(shí)現(xiàn)異步區(qū)別不大,只是使用Future是要獲取執(zhí)行后的返回值

    //創(chuàng)建具有返回值的任務(wù)
    public class CallableThread implements Callable {
        @Override
        public String call() throws Exception {
            long start = System.currentTimeMillis();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            System.out.println("callable任務(wù)開始執(zhí)行:" + start);
            TimeUnit.SECONDS.sleep(2);
            System.out.println();
            stopWatch.stop();
            System.out.println("stopWatch.prettyPrint------");
            System.out.println(stopWatch.prettyPrint());
            System.out.println("stopWatch.shortSummary------");
            System.out.println(stopWatch.shortSummary());
            System.out.println("stopWatch.getTotalTimeMillis------");
            System.out.println(stopWatch.getTotalTimeMillis());
            return "call執(zhí)行結(jié)束 ";
        }
    }
    
    //在業(yè)務(wù)中進(jìn)行調(diào)用
    public String threadFuture(){
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 3, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.AbortPolicy());
        long start = System.currentTimeMillis();
        CallableThread callableThread = new CallableThread();
        Future<String> submit = threadPool.submit(callableThread);
        try {
            //在獲取返回值時(shí)會(huì)阻塞主線程
            String s = "";
            s = submit.get();
            System.out.println(s);
        } catch (Exception e) {
            System.out.println("線程運(yùn)行發(fā)生錯(cuò)誤" + e.getMessage());
            throw new RuntimeException(e);
        }
        long end = System.currentTimeMillis();
        return "接口返回,耗時(shí):" + (end - start);
    }
    

    結(jié)果:Java實(shí)現(xiàn)異步的幾種方式

  3. Spring的@Async異步
    • 使用@Async注解實(shí)現(xiàn)異步的前提是需要在啟動(dòng)類上標(biāo)注@EnableAsync來開啟異步配置

    • 配置線程池(@Async默認(rèn)情況下用的是SimpleAsyncTaskExecutor線程池,該線程池不是真正意義上的線程池,使用此線程池?zé)o法實(shí)現(xiàn)線程重用,每次調(diào)用都會(huì)新建一條線程。若系統(tǒng)中不斷的創(chuàng)建線程,最終會(huì)導(dǎo)致系統(tǒng)占用內(nèi)存過高,引發(fā)OutOfMemoryError錯(cuò)誤)

      /**
       * 線程池配置,可以配置多個(gè)線程池
       * @Async注解,默認(rèn)使用系統(tǒng)自定義線程池,可在項(xiàng)目中設(shè)置多個(gè)線程池,在異步調(diào)用的時(shí)候,指明需要調(diào)用的線程池名稱
       * 比如:@Async("線程池1")
       */
      @Configuration
      public class ExecutorConfig {
          /**
           * 自定義線程池
           */
          @Bean("myExecutor")
          public Executor taskExecutor(){
              System.out.println("系統(tǒng)最大線程數(shù):" + Runtime.getRuntime().availableProcessors());
              ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
              threadPoolTaskExecutor.setCorePoolSize(8);//核心線程數(shù)
              threadPoolTaskExecutor.setMaxPoolSize(16);//最大線程數(shù)
              threadPoolTaskExecutor.setQueueCapacity(1000);//配置隊(duì)列容量
              threadPoolTaskExecutor.setKeepAliveSeconds(60);//空閑線程存活時(shí)間
              threadPoolTaskExecutor.setThreadNamePrefix("myExecutor-");//線程名字前綴
              return threadPoolTaskExecutor;
          }
      }
      
    • 編寫異步方法的邏輯,異步方法所在的類需要被Spring管理

      @Service
      public class AsyncServiceImpl implements AsyncService {
          @Override
          @Async("myExecutor")
          public void sendMsg() {
              System.out.println("進(jìn)入異步方法");
              System.out.println("當(dāng)前線程名稱:" + Thread.currentThread().getName());
              try {
                  TimeUnit.SECONDS.sleep(2);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
              System.out.println("異步方法執(zhí)行完成");
          }
      
          /**
           * 具有返回值的異步方法,返回類型為Future,返回時(shí)new 一個(gè)AsyncResult對(duì)象,其中參數(shù)為返回的內(nèi)容
           * @return
           */
          @Override
          @Async("myExecutor")
          public Future<String> sendMsgFuture() {
              System.out.println("進(jìn)入future異步方法");
              try {
                  TimeUnit.SECONDS.sleep(2);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
              return new AsyncResult<>("future異步方法執(zhí)行完成");
          }
      }
      
    • 在業(yè)務(wù)邏輯中調(diào)用

      @GetMapping("/asyncMethod")
      public String asyncMethod(){
          System.out.println("aaa");
          System.out.println("調(diào)用異步方法");
          asyncService.sendMsg();
          System.out.println("bbb");
          return "asyncMethod方法返回";
      }
      

      調(diào)用沒有返回值的異步方法結(jié)果:Java實(shí)現(xiàn)異步的幾種方式

      @GetMapping("/asyncFutureMethod")
      public String asyncFutureMethod(){
          System.out.println("aaa");
          Future<String> stringFuture = asyncService.sendMsgFuture();
          System.out.println("bbb");
          try {
          System.out.println(stringFuture.get());//get方法會(huì)阻塞主線程
          } catch (Exception e) {
          throw new RuntimeException(e);
          }
          return "asyncfutureMethod方法返回";
      }
      

      調(diào)用有返回值的異步方法結(jié)果:Java實(shí)現(xiàn)異步的幾種方式

  4. Spring的ApplicationEvent事件實(shí)現(xiàn)異步
    • 定義事件,繼承ApplicationEvent類

      public class MessageEvent extends ApplicationEvent {
          @Getter
          private String message;
      
          public MessageEvent(Object source, String message) {
              super(source);
              this.message = message;
          }
      }
      
    • 定義監(jiān)聽器(需要被Spring管理)

      使用@EventListener注解寫在方法上定義一個(gè)監(jiān)聽器,即事件被觸發(fā)時(shí)執(zhí)行的方法(默認(rèn)是同步執(zhí)行,可以使用@Async注解標(biāo)注為異步執(zhí)行),支持多個(gè)監(jiān)聽器監(jiān)聽同一個(gè)事件。

      @Component
      public class MessageEventHandler {
      
          //@Async
          @EventListener
          public void handleLoginEvent(LoginEvent event){
              System.out.println("接受到LoginEvent事件");
              try {
                  TimeUnit.SECONDS.sleep(2);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
              System.out.println(event.getUsername());
              System.out.println("LoginEvent事件處理完成");
          }
      
          //@Async
          @EventListener
          public void handleMessageEvent(MessageEvent event){
              System.out.println("接受到MessageEvent事件");
              try {
                  TimeUnit.SECONDS.sleep(2);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
              System.out.println(event.getMessage());
              System.out.println("MessageEvent事件處理完成");
          }
      }
      
    • 定義事件發(fā)布者(觸發(fā)事件的)(需要被Spring管理)

      實(shí)現(xiàn)ApplicationEventPublisherAware接口

      @Component
      public class EventPublisher implements ApplicationEventPublisherAware {
          private ApplicationEventPublisher publisher;
      
          @Override
          public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
              this.publisher = applicationEventPublisher;
          }
      
          public void publish(ApplicationEvent event){
              if (event instanceof MessageEvent){
                  System.out.println("開始發(fā)布MessageEvent事件:" + ((MessageEvent) event).getMessage());
              } else if (event instanceof LoginEvent) {
                  System.out.println("開始發(fā)布LoginEvent事件:" + ((LoginEvent) event).getUsername());
              }
              //發(fā)布事件
              publisher.publishEvent(event);
              System.out.println("事件發(fā)布結(jié)束");
          }
      
      }
      
    • 業(yè)務(wù)代碼執(zhí)行時(shí)觸發(fā)事件

      @GetMapping("/pubEvent")
      public String publishEvent(){
          System.out.println("業(yè)務(wù)邏輯開始");
          eventPublisher.publish(new MessageEvent(this,"testEvent"));
          System.out.println("業(yè)務(wù)邏輯結(jié)束");
          return "發(fā)布成功";
      }
      

      執(zhí)行結(jié)果:Java實(shí)現(xiàn)異步的幾種方式

      由控制臺(tái)打印可以發(fā)現(xiàn)現(xiàn)在事件監(jiān)聽器方法的執(zhí)行是同步的,如果需要異步執(zhí)行,在監(jiān)聽器方法上加個(gè)@Async注解即可,但使用Async注解的前提是在啟動(dòng)類上標(biāo)注@EnableAsync注解來開啟異步配置

      使用@Async注解后執(zhí)行結(jié)果:Java實(shí)現(xiàn)異步的幾種方式

      可以看到監(jiān)聽器中的打印在最后了,證明是異步執(zhí)行的文章來源地址http://www.zghlxwxcb.cn/news/detail-759990.html

到了這里,關(guān)于Java實(shí)現(xiàn)異步的幾種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 線程間實(shí)現(xiàn)通信的幾種方式

    線程間實(shí)現(xiàn)通信的幾種方式

    線程間通信的模型有兩種:共享內(nèi)存和消息傳遞,下面介紹的都是圍繞這兩個(gè)來實(shí)現(xiàn) 有兩個(gè)線程A和B,B線程向一個(gè)集合里面依次添加元素“abc”字符串,一共添加10次,當(dāng)添加到第五次的時(shí)候,希望線程A能夠收到線程B的通知,然后B線程執(zhí)行相關(guān)的業(yè)務(wù)操作 Object類提供了線程

    2024年02月15日
    瀏覽(24)
  • Qt 多線程的幾種實(shí)現(xiàn)方式

    Qt 多線程的幾種實(shí)現(xiàn)方式

    Qt多線程的實(shí)現(xiàn)方式有: 1. 繼承QThread類,重寫run()方法 2. 使用moveToThread將一個(gè)繼承QObject的子類移至線程,內(nèi)部槽函數(shù)均在線程中執(zhí)行 3. 使用QThreadPool,搭配QRunnable(線程池) 4. 使用QtConcurrent(線程池) 為什么要用線程池? 創(chuàng)建和銷毀線程需要和OS交互,少量線程影響不大,

    2024年02月15日
    瀏覽(23)
  • Java如何實(shí)現(xiàn)下載文件的幾種方式

    版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。 本文鏈接:https://blog.csdn.net/Boy_Martin/article/details/126058565

    2024年02月13日
    瀏覽(30)
  • 創(chuàng)建線程的幾種方式

    創(chuàng)建線程的幾種方式

    線程和進(jìn)程的區(qū)別: 進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的最小單元。 線程是操作系統(tǒng)進(jìn)行任務(wù)分配的最小單元,線程隸屬于進(jìn)程。 如何開啟線程? 1、繼承Thread類,重寫run方法。 2、實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)run方法。 3、實(shí)現(xiàn)Callable接口,實(shí)現(xiàn)call方法。通過FutureTask創(chuàng)建一個(gè)線程,獲

    2024年02月03日
    瀏覽(20)
  • Java生成二維碼的幾種實(shí)現(xiàn)方式

    本文將基于Spring Boot介紹兩種生成二維碼的實(shí)現(xiàn)方式,一種是基于Google開發(fā)工具包,另一種是基于Hutool來實(shí)現(xiàn); 下面我們將基于Spring Boot,并采用兩種方式實(shí)現(xiàn)二維碼的生成,對(duì)于每一種方式還提供兩種類型的二維碼返回形式,即:物理文件 和 圖片響應(yīng)流 一、基于Google開發(fā)

    2024年02月17日
    瀏覽(19)
  • Java實(shí)現(xiàn)字符串排序的幾種方式

    創(chuàng)建實(shí)體類(此處引入了lombok) 一、使用List集合中自帶的sort方法(字符串的位數(shù)保持一致,不一致的情況可以在左邊補(bǔ)0,也可以使用String.format()方法補(bǔ)全) 1、在對(duì)象排序中使用 2、在字符串排序中使用 二、使用Stream流(字符串的位數(shù)保持一致,不一致的情況可以在左邊補(bǔ)

    2024年02月11日
    瀏覽(19)
  • 【Java 干貨教程】Java實(shí)現(xiàn)分頁的幾種方式詳解

    【Java 干貨教程】Java實(shí)現(xiàn)分頁的幾種方式詳解

    無論是自我學(xué)習(xí)中,還是在工作中,固然會(huì)遇到 與前端搭配實(shí)現(xiàn)分頁的功能 ,發(fā)現(xiàn)有幾種方式,特此記錄一下。 這種情況也是有的,(根據(jù)業(yè)務(wù)場(chǎng)景且僅僅只能用于 數(shù)據(jù)量少 的情況)。即后端不做任何數(shù)據(jù)的限制,直接把全部數(shù)據(jù)返回給前端,前端通過組件實(shí)現(xiàn)分頁,篩選等

    2024年02月02日
    瀏覽(29)
  • java實(shí)現(xiàn)調(diào)用http請(qǐng)求的幾種常見方式

    java實(shí)現(xiàn)調(diào)用http請(qǐng)求的幾種常見方式

    ------ Oracle中文開發(fā)者社區(qū) ------ 如果你想要學(xué)習(xí)編程,關(guān)注本博客,持續(xù)獲得技術(shù)支持,持續(xù)獲得技術(shù)咨詢 java開發(fā)·企業(yè)官方賬號(hào) Oracle中國官方賬號(hào) Java中國管理部 全網(wǎng)粉絲30萬+ 華為云享專家 阿里專家博主 CSDN內(nèi)容合伙人 CSDN原力計(jì)劃作者 51CTO專家博主 CSDN博客V賬號(hào) 畢業(yè)于四川

    2024年02月04日
    瀏覽(21)
  • JAVA微服務(wù)分布式事務(wù)的幾種實(shí)現(xiàn)方式

    JAVA微服務(wù)分布式事務(wù)的幾種實(shí)現(xiàn)方式

    一致性(Consistency) :在分布式系統(tǒng)中所有的數(shù)據(jù)備份,在同一時(shí)刻都保持一致狀態(tài),如無法保證狀態(tài)一致,直接返回錯(cuò)誤; 可用性(Availability):在集群中一部分節(jié)點(diǎn)故障,也能保證客戶端訪問系統(tǒng)并得到正確響應(yīng),允許一定時(shí)間內(nèi)數(shù)據(jù)狀態(tài)不一致; 分區(qū)容錯(cuò)性(Partiti

    2024年02月12日
    瀏覽(20)
  • Java實(shí)現(xiàn)HTTP請(qǐng)求的幾種方式-CloseableHttpClient(三)

    Java實(shí)現(xiàn)HTTP請(qǐng)求的幾種方式-CloseableHttpClient(三)

    CloseableHttpClient是在HttpClient的基礎(chǔ)上修改更新而來的,這里還涉及到請(qǐng)求頭token的設(shè)置(請(qǐng)求驗(yàn)證),利用fastjson轉(zhuǎn)換請(qǐng)求或返回結(jié)果字符串為json格式,當(dāng)然上面兩種方式也是可以設(shè)置請(qǐng)求頭token、json的,這里只在下面說明。 基于第一章的測(cè)試接口,建立以下程序 創(chuàng)建客戶端

    2023年04月20日
    瀏覽(100)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包