1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢(xún)
      選擇下列產(chǎn)品馬上在線(xiàn)溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
      如何使用Springboot線(xiàn)程池

      今天就跟大家聊聊有關(guān)如何使用Springboot線(xiàn)程池,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

      創(chuàng)新互聯(lián)建站2013年至今,先為平房等服務(wù)建站,平房等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為平房企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

       創(chuàng)建springboot工程

      用IntelliJ IDEA創(chuàng)建一個(gè)springboot的web工程threadpooldemoserver,pom.xml內(nèi)容如下:

      
      
          4.0.0
      
          com.vincent
          threadpooldemoserver
          1.0-SNAPSHOT
      
          
              UTF-8
              1.8
              1.8
          
      
          
              
                  
                      org.springframework.boot
                      spring-boot-dependencies
                      2.1.4.RELEASE
                      import
                      pom
                  
              
          
      
          
      
              
                  org.springframework.boot
                  spring-boot-starter-web
              
              
                  org.projectlombok
                  lombok
                  1.18.6
              
          
      
          
              
                  
                      org.springframework.boot
                      spring-boot-maven-plugin
                      2.1.4.RELEASE
                      
                          cn.ac.iie.App
                      
                      
                          
                              
                                  repackage
                              
                          
                      
                  
      
                  
                      org.apache.maven.plugins
                      maven-surefire-plugin
                      
                          true
                      
                  
              
          
      
      

      創(chuàng)建Service層的接口和實(shí)現(xiàn)

      創(chuàng)建一個(gè)service層的接口AsyncService,如下:

      public interface AsyncService {
          /**
           * 執(zhí)行異步任務(wù)
           */
          void executeAsync();
      }

      對(duì)應(yīng)的AsyncServiceImpl,實(shí)現(xiàn)如下:

      @Service
      @Slf4j
      public class AsyncServiceImpl implements AsyncService {
      
          @Override
          public void executeAsync() {
              log.info("start executeAsync");
              try{
                  Thread.sleep(1000);
              }catch(Exception e){
                  e.printStackTrace();
              }
              log.info("end executeAsync");
          }
      }

      這個(gè)方法做的事情很簡(jiǎn)單:sleep了一秒鐘;

      創(chuàng)建controller

      創(chuàng)建一個(gè)controller為Hello,里面定義一個(gè)http接口,做的事情是調(diào)用Service層的服務(wù),如下:

      @RestController
      @Slf4j
      public class Hello {
          @Autowired
          private AsyncService asyncService;
      
          @RequestMapping("/")
          public String submit() {
              log.info("start submit");
              //調(diào)用service層的任務(wù)
              asyncService.executeAsync();
              log.info("end submit");
              return "success";
          }
      }

      至此,我們已經(jīng)做好了一個(gè)http請(qǐng)求的服務(wù),里面做的事情其實(shí)是同步的,接下來(lái)我們就開(kāi)始配置springboot的線(xiàn)程池服務(wù),將service層做的事情都提交到線(xiàn)程池中去處理;

      springboot的線(xiàn)程池配置

      創(chuàng)建一個(gè)配置類(lèi)ExecutorConfig,用來(lái)定義如何創(chuàng)建一個(gè)ThreadPoolTaskExecutor,要使用@Configuration和@EnableAsync這兩個(gè)注解,表示這是個(gè)配置類(lèi),并且是線(xiàn)程池的配置類(lèi),如下所示:

      @Configuration
      @EnableAsync
      @Slf4j
      public class ExecutorConfig {
          @Bean
          public Executor asyncServiceExecutor() {
              log.info("start asyncServiceExecutor");
              ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
              //配置核心線(xiàn)程數(shù)
              executor.setCorePoolSize(5);
              //配置最大線(xiàn)程數(shù)
              executor.setMaxPoolSize(5);
              //配置隊(duì)列大小
              executor.setQueueCapacity(99999);
              //配置線(xiàn)程池中的線(xiàn)程的名稱(chēng)前綴
              executor.setThreadNamePrefix("async-service-");
      
              // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)
              // CALLER_RUNS:不在新線(xiàn)程中執(zhí)行任務(wù),而是有調(diào)用者所在的線(xiàn)程來(lái)執(zhí)行
              executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
              //執(zhí)行初始化
              executor.initialize();
              return executor;
          }
      }

      注意,上面的方法名稱(chēng)為asyncServiceExecutor,稍后馬上用到;

      將Service層的服務(wù)異步化

      打開(kāi)AsyncServiceImpl.java,在executeAsync方法上增加注解@Async(“asyncServiceExecutor”),asyncServiceExecutor是前面ExecutorConfig.java中的方法名,表明executeAsync方法進(jìn)入的線(xiàn)程池是asyncServiceExecutor方法創(chuàng)建的,如下:

      @Service
      @Slf4j
      public class AsyncServiceImpl implements AsyncService {
      
          @Override
          @Async("asyncServiceExecutor")
          public void executeAsync() {
              log.info("start executeAsync");
              try{
                  Thread.sleep(1000);
              }catch(Exception e){
                  e.printStackTrace();
              }
              log.info("end executeAsync");
          }
      }

      驗(yàn)證效果

      1. 將這個(gè)springboot運(yùn)行起來(lái)(pom.xml所在文件夾下執(zhí)行mvn spring-boot:run);

      2. 在瀏覽器輸入:http://localhost:8080;

      3. 在瀏覽器用F5按鈕快速多刷新幾次;

      4. 在springboot的控制臺(tái)看見(jiàn)日志如下:

      2019-08-12 15:23:00.320  INFO 5848 --- [nio-8080-exec-2] cn.ac.iie.controller.Hello               : start submit
      2019-08-12 15:23:00.327  INFO 5848 --- [nio-8080-exec-2] cn.ac.iie.controller.Hello               : end submit
      2019-08-12 15:23:00.327  INFO 5848 --- [async-service-1] cn.ac.iie.service.impl.AsyncServiceImpl  : start executeAsync
      2019-08-12 15:23:01.329  INFO 5848 --- [async-service-1] cn.ac.iie.service.impl.AsyncServiceImpl  : end executeAsync
      2019-08-12 15:24:17.449  INFO 5848 --- [nio-8080-exec-5] cn.ac.iie.controller.Hello               : start submit
      2019-08-12 15:24:17.450  INFO 5848 --- [nio-8080-exec-5] cn.ac.iie.controller.Hello               : end submit
      2019-08-12 15:24:17.450  INFO 5848 --- [async-service-2] cn.ac.iie.service.impl.AsyncServiceImpl  : start executeAsync
      2019-08-12 15:24:18.125  INFO 5848 --- [nio-8080-exec-6] cn.ac.iie.controller.Hello               : start submit
      2019-08-12 15:24:18.126  INFO 5848 --- [nio-8080-exec-6] cn.ac.iie.controller.Hello               : end submit
      2019-08-12 15:24:18.128  INFO 5848 --- [async-service-3] cn.ac.iie.service.impl.AsyncServiceImpl  : start executeAsync
      2019-08-12 15:24:18.451  INFO 5848 --- [async-service-2] cn.ac.iie.service.impl.AsyncServiceImpl  : end executeAsync
      2019-08-12 15:24:18.685  INFO 5848 --- [nio-8080-exec-7] cn.ac.iie.controller.Hello               : start submit
      2019-08-12 15:24:18.688  INFO 5848 --- [nio-8080-exec-7] cn.ac.iie.controller.Hello               : end submit
      2019-08-12 15:24:18.703  INFO 5848 --- [async-service-4] cn.ac.iie.service.impl.AsyncServiceImpl  : start executeAsync
      2019-08-12 15:24:19.130  INFO 5848 --- [async-service-3] cn.ac.iie.service.impl.AsyncServiceImpl  : end executeAsync
      2019-08-12 15:24:19.704  INFO 5848 --- [async-service-4] cn.ac.iie.service.impl.AsyncServiceImpl  : end executeAsync

       如上日志所示,我們可以看到controller的執(zhí)行線(xiàn)程是"nio-8080-exec-5",這是tomcat的執(zhí)行線(xiàn)程,而service層的日志顯示線(xiàn)程名為“async-service-1”,顯然已經(jīng)在我們配置的線(xiàn)程池中執(zhí)行了,并且每次請(qǐng)求中,controller的起始和結(jié)束日志都是連續(xù)打印的,表明每次請(qǐng)求都快速響應(yīng)了,而耗時(shí)的操作都留給線(xiàn)程池中的線(xiàn)程去異步執(zhí)行;

      擴(kuò)展ThreadPoolTaskExecutor

      雖然我們已經(jīng)用上了線(xiàn)程池,但是還不清楚線(xiàn)程池當(dāng)時(shí)的情況,有多少線(xiàn)程在執(zhí)行,多少在隊(duì)列中等待呢?這里我創(chuàng)建了一個(gè)ThreadPoolTaskExecutor的子類(lèi),在每次提交線(xiàn)程的時(shí)候都會(huì)將當(dāng)前線(xiàn)程池的運(yùn)行狀況打印出來(lái),代碼如下:

      @Slf4j
      public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
          private void showThreadPoolInfo(String prefix){
              ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();
      
              if(null==threadPoolExecutor){
                  return;
              }
      
              log.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
                      this.getThreadNamePrefix(),
                      prefix,
                      threadPoolExecutor.getTaskCount(),
                      threadPoolExecutor.getCompletedTaskCount(),
                      threadPoolExecutor.getActiveCount(),
                      threadPoolExecutor.getQueue().size());
          }
      
          @Override
          public void execute(Runnable task) {
              showThreadPoolInfo("1. do execute");
              super.execute(task);
          }
      
          @Override
          public void execute(Runnable task, long startTimeout) {
              showThreadPoolInfo("2. do execute");
              super.execute(task, startTimeout);
          }
      
          @Override
          public Future submit(Runnable task) {
              showThreadPoolInfo("1. do submit");
              return super.submit(task);
          }
      
          @Override
          public  Future submit(Callable task) {
              showThreadPoolInfo("2. do submit");
              return super.submit(task);
          }
      
          @Override
          public ListenableFuture submitListenable(Runnable task) {
              showThreadPoolInfo("1. do submitListenable");
              return super.submitListenable(task);
          }
      
          @Override
          public  ListenableFuture submitListenable(Callable task) {
              showThreadPoolInfo("2. do submitListenable");
              return super.submitListenable(task);
          }
      }

      如上所示,showThreadPoolInfo方法中將任務(wù)總數(shù)、已完成數(shù)、活躍線(xiàn)程數(shù),隊(duì)列大小都打印出來(lái)了,然后Override了父類(lèi)的execute、submit等方法,在里面調(diào)用showThreadPoolInfo方法,這樣每次有任務(wù)被提交到線(xiàn)程池的時(shí)候,都會(huì)將當(dāng)前線(xiàn)程池的基本情況打印到日志中;

      修改ExecutorConfig.java的asyncServiceExecutor方法,將ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor()改為T(mén)hreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor(),如下所示:

          @Bean
          public Executor asyncServiceExecutor() {
              log.info("start asyncServiceExecutor");
              ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
              //配置核心線(xiàn)程數(shù)
              executor.setCorePoolSize(5);
              //配置最大線(xiàn)程數(shù)
              executor.setMaxPoolSize(5);
              //配置隊(duì)列大小
              executor.setQueueCapacity(99999);
              //配置線(xiàn)程池中的線(xiàn)程的名稱(chēng)前綴
              executor.setThreadNamePrefix("async-service-");
      
              // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)
              // CALLER_RUNS:不在新線(xiàn)程中執(zhí)行任務(wù),而是有調(diào)用者所在的線(xiàn)程來(lái)執(zhí)行
              executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
              //執(zhí)行初始化
              executor.initialize();
              return executor;
          }

      修改hello.java,方便查看線(xiàn)程池結(jié)果:

          @RequestMapping("/")
          public Object submit() {
              log.info("start submit");
              //調(diào)用service層的任務(wù)
              asyncService.executeAsync();
              log.info("end submit");
              JSONObject jsonObject = new JSONObject();
              ThreadPoolExecutor threadPoolExecutor = visiableThreadPoolTaskExecutor.getThreadPoolExecutor();
              jsonObject.put("ThreadNamePrefix", visiableThreadPoolTaskExecutor.getThreadNamePrefix());
              jsonObject.put("TaskCount", threadPoolExecutor.getTaskCount());
              jsonObject.put("completedTaskCount", threadPoolExecutor.getCompletedTaskCount());
              jsonObject.put("activeCount", threadPoolExecutor.getActiveCount());
              jsonObject.put("queueSize", threadPoolExecutor.getQueue().size());
              return jsonObject;
          }

      再次啟動(dòng)該工程,再瀏覽器反復(fù)刷新http://localhost:8080,看到的日志如下:

      {
          "activeCount": 2,
          "queueSize": 1,
          "TaskCount": 26,
          "completedTaskCount": 23,
          "ThreadNamePrefix": "async-service-"
      }

      看完上述內(nèi)容,你們對(duì)如何使用Springboot線(xiàn)程池有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。


      新聞名稱(chēng):如何使用Springboot線(xiàn)程池
      標(biāo)題路徑:http://www.ef60e0e.cn/article/gsideh.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        固安县| 乌兰县| 桂林市| 屯留县| 惠东县| 桑植县| 大新县| 故城县| 象州县| 英山县| 瑞昌市| 讷河市| 成都市| 神池县| 深州市| 定远县| 祁东县| 澄迈县| 长泰县| 镇赉县| 安徽省| 时尚| 合川市| 玉林市| 康平县| 隆子县| 克什克腾旗| 常宁市| 嘉祥县| 恩施市| 康定县| 黑水县| 婺源县| 集贤县| 甘孜| 龙泉市| 巴东县| 酉阳| 房产| 桃江县| 屏山县|