一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot 多任務并行+線程池處理的實現

SpringBoot 多任務并行+線程池處理的實現

2021-04-23 11:24小柒 Java教程

這篇文章主要介紹了SpringBoot 多任務并行+線程池處理的實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

前幾篇文章著重介紹了后端服務數據庫和多線程并行處理優化,并示例了改造前后的偽代碼邏輯。當然了,優化是無止境的,前人栽樹后人乘涼。作為我們開發者來說,既然站在了巨人的肩膀上,就要寫出更加優化的程序。

springboot開發案例之jdbctemplate批量操作
springboot開發案例之countdownlatch多任務并行處理

改造

理論上講,線程越多程序可能更快,但是在實際使用中我們需要考慮到線程本身的創建以及銷毀的資源消耗,以及保護操作系統本身的目的。我們通常需要將線程限制在一定的范圍之類,線程池就起到了這樣的作用。

程序邏輯

SpringBoot 多任務并行+線程池處理的實現

多任務并行+線程池處理.png

一張圖能解決的問題,就應該盡可能的少bb,當然底層原理性的東西還是需要大家去記憶并理解的。

java 線程池

java通過executors提供四種線程池,分別為:

  1. newcachedthreadpool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
  2. newfixedthreadpool 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
  3. newscheduledthreadpool 創建一個定長線程池,支持定時及周期性任務執行。
  4. newsinglethreadexecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(fifo, lifo, 優先級)執行。

優點

  1. 重用存在的線程,減少對象創建、消亡的開銷,性能佳。
  2. 可有效控制最大并發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
  3. 提供定時執行、定期執行、單線程、并發數控制等功能。

代碼實現

方式一(countdownlatch)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
 * 多任務并行+線程池統計
 * 創建時間  2018年4月17日
 */
public class statsdemo {
  final static simpledateformat sdf = new simpledateformat(
      "yyyy-mm-dd hh:mm:ss");
  
  final static string starttime = sdf.format(new date());
  
  /**
   * io密集型任務 = 一般為2*cpu核心數(常出現于線程中:數據庫數據交互、文件上傳下載、網絡數據傳輸等等)
   * cpu密集型任務 = 一般為cpu核心數+1(常出現于線程中:復雜算法)
   * 混合型任務 = 視機器配置和復雜度自測而定
   */
  private static int corepoolsize = runtime.getruntime().availableprocessors();
  /**
   * public threadpoolexecutor(int corepoolsize,int maximumpoolsize,long keepalivetime,
   *              timeunit unit,blockingqueue<runnable> workqueue)
   * corepoolsize用于指定核心線程數量
   * maximumpoolsize指定最大線程數
   * keepalivetime和timeunit指定線程空閑后的最大存活時間
   * workqueue則是線程池的緩沖隊列,還未執行的線程會在隊列中等待
   * 監控隊列長度,確保隊列有界
   * 不當的線程池大小會使得處理速度變慢,穩定性下降,并且導致內存泄露。如果配置的線程過少,則隊列會持續變大,消耗過多內存。
   * 而過多的線程又會 由于頻繁的上下文切換導致整個系統的速度變緩——殊途而同歸。隊列的長度至關重要,它必須得是有界的,這樣如果線程池不堪重負了它可以暫時拒絕掉新的請求。
   * executorservice 默認的實現是一個無界的 linkedblockingqueue。
   */
  private static threadpoolexecutor executor = new threadpoolexecutor(corepoolsize, corepoolsize+1, 10l, timeunit.seconds,
      new linkedblockingqueue<runnable>(1000));
  
  public static void main(string[] args) throws interruptedexception {
    countdownlatch latch = new countdownlatch(5);
    //使用execute方法
     executor.execute(new stats("任務a", 1000, latch));
     executor.execute(new stats("任務b", 1000, latch));
     executor.execute(new stats("任務c", 1000, latch));
     executor.execute(new stats("任務d", 1000, latch));
     executor.execute(new stats("任務e", 1000, latch));
    latch.await();// 等待所有人任務結束
    system.out.println("所有的統計任務執行完成:" + sdf.format(new date()));
  }
 
  static class stats implements runnable {
    string statsname;
    int runtime;
    countdownlatch latch;
 
    public stats(string statsname, int runtime, countdownlatch latch) {
      this.statsname = statsname;
      this.runtime = runtime;
      this.latch = latch;
    }
 
    public void run() {
      try {
        system.out.println(statsname+ " do stats begin at "+ starttime);
        //模擬任務執行時間
        thread.sleep(runtime);
        system.out.println(statsname + " do stats complete at "+ sdf.format(new date()));
        latch.countdown();//單次任務結束,計數器減一
      } catch (interruptedexception e) {
        e.printstacktrace();
      }
    }
  }
}

方式二(future)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
 * 多任務并行+線程池統計
 * 創建時間  2018年4月17日
 */
public class statsdemo {
  final static simpledateformat sdf = new simpledateformat(
      "yyyy-mm-dd hh:mm:ss");
  
  final static string starttime = sdf.format(new date());
  
  /**
   * io密集型任務 = 一般為2*cpu核心數(常出現于線程中:數據庫數據交互、文件上傳下載、網絡數據傳輸等等)
   * cpu密集型任務 = 一般為cpu核心數+1(常出現于線程中:復雜算法)
   * 混合型任務 = 視機器配置和復雜度自測而定
   */
  private static int corepoolsize = runtime.getruntime().availableprocessors();
  /**
   * public threadpoolexecutor(int corepoolsize,int maximumpoolsize,long keepalivetime,
   *              timeunit unit,blockingqueue<runnable> workqueue)
   * corepoolsize用于指定核心線程數量
   * maximumpoolsize指定最大線程數
   * keepalivetime和timeunit指定線程空閑后的最大存活時間
   * workqueue則是線程池的緩沖隊列,還未執行的線程會在隊列中等待
   * 監控隊列長度,確保隊列有界
   * 不當的線程池大小會使得處理速度變慢,穩定性下降,并且導致內存泄露。如果配置的線程過少,則隊列會持續變大,消耗過多內存。
   * 而過多的線程又會 由于頻繁的上下文切換導致整個系統的速度變緩——殊途而同歸。隊列的長度至關重要,它必須得是有界的,這樣如果線程池不堪重負了它可以暫時拒絕掉新的請求。
   * executorservice 默認的實現是一個無界的 linkedblockingqueue。
   */
  private static threadpoolexecutor executor = new threadpoolexecutor(corepoolsize, corepoolsize+1, 10l, timeunit.seconds,
      new linkedblockingqueue<runnable>(1000));
  
  public static void main(string[] args) throws interruptedexception {
    list<future<string>> resultlist = new arraylist<future<string>>();
    //使用submit提交異步任務,并且獲取返回值為future
    resultlist.add(executor.submit(new stats("任務a", 1000)));
    resultlist.add(executor.submit(new stats("任務b", 1000)));
    resultlist.add(executor.submit(new stats("任務c", 1000)));
    resultlist.add(executor.submit(new stats("任務d", 1000)));
    resultlist.add(executor.submit(new stats("任務e", 1000)));
     //遍歷任務的結果
    for (future<string> fs : resultlist) {
      try {
        system.out.println(fs.get());//打印各個線任務執行的結果,調用future.get() 阻塞主線程,獲取異步任務的返回結果
      } catch (interruptedexception e) {
        e.printstacktrace();
      } catch (executionexception e) {
        e.printstacktrace();
      } finally {
        //啟動一次順序關閉,執行以前提交的任務,但不接受新任務。如果已經關閉,則調用沒有其他作用。
        executor.shutdown();
      }
    }
    system.out.println("所有的統計任務執行完成:" + sdf.format(new date()));
  }
 
  static class stats implements callable<string> {
    string statsname;
    int runtime;
 
    public stats(string statsname, int runtime) {
      this.statsname = statsname;
      this.runtime = runtime;
    }
 
    public string call() {
      try {
        system.out.println(statsname+ " do stats begin at "+ starttime);
        //模擬任務執行時間
        thread.sleep(runtime);
        system.out.println(statsname + " do stats complete at "+ sdf.format(new date()));
      } catch (interruptedexception e) {
        e.printstacktrace();
      }
      return call();
    }
  }
}

執行時間

以上代碼,均是偽代碼,下面是2000+個學生的真實測試記錄。

2018-04-17 17:42:29.284 info   測試記錄81e51ab031eb4ada92743ddf66528d82-單線程順序執行,花費時間:3797
2018-04-17 17:42:31.452 info   測試記錄81e51ab031eb4ada92743ddf66528d82-多線程并行任務,花費時間:2167
2018-04-17 17:42:33.170 info   測試記錄81e51ab031eb4ada92743ddf66528d82-多線程并行任務+線程池,花費時間:1717

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.52itstyle.com/archives/2705/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 护士让我吃奶我扒她奶 | 性一交一无一伦一精一品 | 精品手机在线1卡二卡3卡四卡 | 色在线影院| 激情影院免费 | 久久re视频这里精品一本到99 | 国产日韩片 | 美女禁区视频无遮挡免费看 | 精品亚洲欧美中文字幕在线看 | 国产精品二区高清在线 | 青青草在视线频久久 | 亚洲精品第二页 | 欧美日韩一区二区中文字幕视频 | 免费全看男女拍拍拍的视频 | 91久久国产露脸精品 | 国产香蕉久久 | 日韩在线观看网站 | 日韩久久网 | 美女一级ba大片免色 | 俺去俺去啦最新官网在线 | 日本特级a禁片在线播放 | 日本黄色大片免费观看 | 亚洲第一成年免费网站 | 我的美女奴隶 | 99久久精彩视频 | 人与动人物性行为zozo共患病 | 湿好紧太硬了我太爽了 | 亚洲久草 | 白俄罗斯bbbsss | 91精品国产高清久久久久久io | 亚洲国产成人资源在线桃色 | 色婷婷久久综合中文久久一本 | 精品精品国产自在香蕉网 | 无码AV免费精品一区二区三区 | 亚洲精品福利在线 | 男女拍拍拍免费视频网站 | 国产区成人综合色在线 | 91探花在线观看 | 双性鞭蒂软汁淋漓 | 无人区尖叫之夜美女姐姐视频 | 国产亚洲欧美一区二区三区 |