精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Go 中的 Channel 與 Java BlockingQueue 的本質區別

開發 后端
最近在實現兩個需求,由于兩者之間并沒有依賴關系,所以想利用隊列進行解耦;但在 Go 的標準庫中并沒有現成可用并且并發安全的數據結構;但 Go 提供了一個更加優雅的解決方案,那就是 channel。

[[408793]]

本文轉載自微信公眾號「crossoverJie」,作者crossoverJie。轉載本文請聯系crossoverJie公眾號。

前言

最近在實現兩個需求,由于兩者之間并沒有依賴關系,所以想利用隊列進行解耦;但在 Go 的標準庫中并沒有現成可用并且并發安全的數據結構;但 Go 提供了一個更加優雅的解決方案,那就是 channel。

channel 應用

Go 與 Java 的一個很大的區別就是并發模型不同,Go 采用的是 CSP(Communicating sequential processes) 模型;用 Go 官方的說法:

Do not communicate by sharing memory; instead, share memory by communicating.

翻譯過來就是:不用使用共享內存來通信,而是用通信來共享內存。

而這里所提到的通信,在 Go 里就是指代的 channel。

只講概念并不能快速的理解與應用,所以接下來會結合幾個實際案例更方便理解。

futrue task

Go 官方沒有提供類似于 Java 的 FutureTask 支持:

  1.     public static void main(String[] args) throws InterruptedException, ExecutionException { 
  2.         ExecutorService executorService = Executors.newFixedThreadPool(2); 
  3.         Task task = new Task(); 
  4.         FutureTask<String> futureTask = new FutureTask<>(task); 
  5.         executorService.submit(futureTask); 
  6.         String s = futureTask.get(); 
  7.         System.out.println(s); 
  8.         executorService.shutdown(); 
  9.     } 
  10.  
  11. class Task implements Callable<String> { 
  12.     @Override 
  13.     public String call() throws Exception { 
  14.         // 模擬http 
  15.         System.out.println("http request"); 
  16.         Thread.sleep(1000); 
  17.  
  18.         return "request success"
  19.     } 

但我們可以使用 channel 配合 goroutine 實現類似的功能:

  1. func main() { 
  2.  ch := Request("https://github.com"
  3.  select { 
  4.  case r := <-ch: 
  5.   fmt.Println(r) 
  6.  } 
  7. func Request(url string) <-chan string { 
  8.  ch := make(chan string) 
  9.  go func() { 
  10.   // 模擬http請求 
  11.   time.Sleep(time.Second
  12.   ch <- fmt.Sprintf("url=%s, res=%s", url, "ok"
  13.  }() 
  14.  return ch 

goroutine 發起請求后直接將這個 channel 返回,調用方會在請求響應之前一直阻塞,直到 goroutine 拿到了響應結果。

goroutine 互相通信

  1. /** 
  2.   * 偶數線程 
  3.   */ 
  4.  public static class OuNum implements Runnable { 
  5.      private TwoThreadWaitNotifySimple number; 
  6.  
  7.      public OuNum(TwoThreadWaitNotifySimple number) { 
  8.          this.number = number; 
  9.      } 
  10.  
  11.      @Override 
  12.      public void run() { 
  13.          for (int i = 0; i < 11; i++) { 
  14.              synchronized (TwoThreadWaitNotifySimple.class) { 
  15.                  if (number.flag) { 
  16.                      if (i % 2 == 0) { 
  17.                          System.out.println(Thread.currentThread().getName() + "+-+偶數" + i); 
  18.  
  19.                          number.flag = false
  20.                          TwoThreadWaitNotifySimple.class.notify(); 
  21.                      } 
  22.  
  23.                  } else { 
  24.                      try { 
  25.                          TwoThreadWaitNotifySimple.class.wait(); 
  26.                      } catch (InterruptedException e) { 
  27.                          e.printStackTrace(); 
  28.                      } 
  29.                  } 
  30.              } 
  31.          } 
  32.      } 
  33.  } 
  34.  
  35.  
  36.  /** 
  37.   * 奇數線程 
  38.   */ 
  39.  public static class JiNum implements Runnable { 
  40.      private TwoThreadWaitNotifySimple number; 
  41.  
  42.      public JiNum(TwoThreadWaitNotifySimple number) { 
  43.          this.number = number; 
  44.      } 
  45.  
  46.      @Override 
  47.      public void run() { 
  48.          for (int i = 0; i < 11; i++) { 
  49.              synchronized (TwoThreadWaitNotifySimple.class) { 
  50.                  if (!number.flag) { 
  51.                      if (i % 2 == 1) { 
  52.                          System.out.println(Thread.currentThread().getName() + "+-+奇數" + i); 
  53.  
  54.                          number.flag = true
  55.                          TwoThreadWaitNotifySimple.class.notify(); 
  56.                      } 
  57.  
  58.                  } else { 
  59.                      try { 
  60.                          TwoThreadWaitNotifySimple.class.wait(); 
  61.                      } catch (InterruptedException e) { 
  62.                          e.printStackTrace(); 
  63.                      } 
  64.                  } 
  65.              } 
  66.          } 
  67.      } 
  68.  } 

這里截取了”兩個線程交替打印奇偶數“的部分代碼。

Java 提供了 object.wait()/object.notify() 這樣的等待通知機制,可以實現兩個線程間通信。

go 通過 channel 也能實現相同效果:

  1. func main() { 
  2.  ch := make(chan struct{}) 
  3.  go func() { 
  4.   for i := 1; i < 11; i++ { 
  5.    ch <- struct{}{} 
  6.    //奇數 
  7.    if i%2 == 1 { 
  8.     fmt.Println("奇數:", i) 
  9.    } 
  10.   } 
  11.  }() 
  12.  
  13.  go func() { 
  14.   for i := 1; i < 11; i++ { 
  15.    <-ch 
  16.    if i%2 == 0 { 
  17.     fmt.Println("偶數:", i) 
  18.    } 
  19.   } 
  20.  }() 
  21.  
  22.  time.Sleep(10 * time.Second

本質上他們都是利用了線程(goroutine)阻塞然后喚醒的特性,只是 Java 是通過 wait/notify 機制;

而 go 提供的 channel 也有類似的特性:

向 channel 發送數據時(ch<-struct{}{})會被阻塞,直到 channel 被消費(<-ch)。

以上針對于無緩沖 channel。

channel 本身是由 go 原生保證并發安全的,不用額外的同步措施,可以放心使用。

廣播通知

不僅是兩個 goroutine 之間通信,同樣也能廣播通知,類似于如下 Java 代碼:

  1. public static void main(String[] args) throws InterruptedException { 
  2.     for (int i = 0; i < 10; i++) { 
  3.         new Thread(() -> { 
  4.             try { 
  5.                 synchronized (NotifyAll.class){ 
  6.                     NotifyAll.class.wait(); 
  7.                 } 
  8.                 System.out.println(Thread.currentThread().getName() + "done...."); 
  9.             } catch (InterruptedException e) { 
  10.                 e.printStackTrace(); 
  11.             } 
  12.         }).start(); 
  13.     } 
  14.     Thread.sleep(3000); 
  15.     synchronized (NotifyAll.class){ 
  16.         NotifyAll.class.notifyAll(); 
  17.     } 

主線程將所有等待的子線程全部喚醒,這個本質上也是通過 wait/notify 機制實現的,區別只是通知了所有等待的線程。

換做是 go 的實現:

  1. func main() { 
  2.  notify := make(chan struct{}) 
  3.  for i := 0; i < 10; i++ { 
  4.   go func(i int) { 
  5.    for { 
  6.     select { 
  7.     case <-notify: 
  8.      fmt.Println("done.......",i) 
  9.      return 
  10.     case <-time.After(1 * time.Second): 
  11.      fmt.Println("wait notify",i) 
  12.  
  13.     } 
  14.    } 
  15.   }(i) 
  16.  } 
  17.  time.Sleep(1 * time.Second
  18.  close(notify) 
  19.  time.Sleep(3 * time.Second

當關閉一個 channel 后,會使得所有獲取 channel 的 goroutine 直接返回,不會阻塞,正是利用這一特性實現了廣播通知所有 goroutine 的目的。

注意,同一個 channel 不能反復關閉,不然會出現panic。

channel 解耦

以上例子都是基于無緩沖的 channel,通常用于 goroutine 之間的同步;同時 channel 也具備緩沖的特性:

  1. ch :=make(chan T, 100) 

可以直接將其理解為隊列,正是因為具有緩沖能力,所以我們可以將業務之間進行解耦,生產方只管往 channel 中丟數據,消費者只管將數據取出后做自己的業務。

同時也具有阻塞隊列的特性:

  • 當 channel 寫滿時生產者將會被阻塞。
  • 當 channel 為空時消費者也會阻塞。

從上文的例子中可以看出,實現相同的功能 go 的寫法會更加簡單直接,相對的 Java 就會復雜許多(當然這也和這里使用的偏底層 api 有關)。

Java 中的 BlockingQueue

這些特性都與 Java 中的 BlockingQueue 非常類似,他們具有以下的相同點:

  • 可以通過兩者來進行 goroutine/thread 通信。
  • 具備隊列的特征,可以解耦業務。
  • 支持并發安全。

同樣的他們又有很大的區別,從表現上看:

  • channel 支持 select 語法,對 channel 的管理更加簡潔直觀。
  • channel 支持關閉,不能向已關閉的 channel 發送消息。
  • channel 支持定義方向,在編譯器的幫助下可以在語義上對行為的描述更加準確。

當然還有本質上的區別就是 channel 是 go 推薦的 CSP 模型的核心,具有編譯器的支持,可以有很輕量的成本實現并發通信。

而 BlockingQueue 對于 Java 來說只是一個實現了并發安全的數據結構,即便不使用它也有其他的通信方式;只是他們都具有阻塞隊列的特征,所有在初步接觸 channel 時容易產生混淆。

相同點 channel 特有
阻塞策略 支持select
設置大小 支持關閉
并發安全 自定義方向
普通數據結構 編譯器支持

總結

有過一門編程語言的使用經歷在學習其他語言是確實是要方便許多,比如之前寫過 Java 再看 Go 時就會發現許多類似之處,只是實現不同。

拿這里的并發通信來說,本質上是因為并發模型上的不同;

Go 更推薦使用通信來共享內存,而 Java 大部分場景都是使用共享內存來通信(這樣就得加鎖來同步)。

 

帶著疑問來學習確實會事半功倍。

 

責任編輯:武曉燕 來源: crossoverJie
相關推薦

2011-05-25 13:10:40

SQL ServerOracle

2010-09-27 11:24:37

SQL聚簇索引

2024-09-23 22:48:46

數據中臺數據飛輪數據驅動

2009-07-12 13:55:29

2017-05-27 09:58:42

BGP動態靜態

2018-02-06 14:32:03

云服務器本質區別

2023-05-29 09:25:38

GolangSelect

2025-03-04 10:45:19

JVM內存模型Java

2017-09-25 16:21:30

Spark on yacluster模式

2025-04-17 07:41:07

進程線程窗口

2023-01-03 18:32:32

2020-12-21 06:18:15

Android線程主線程

2025-07-14 06:10:00

Go編程代碼

2018-09-17 14:51:11

信息化數字化區別

2021-11-30 08:57:43

GETPOSTJava

2024-03-11 08:34:43

同步異步調用

2024-03-07 13:30:44

Java對象true

2021-11-10 15:18:16

JavaGo命令

2024-12-03 15:15:22

2011-11-29 09:14:48

JavaError異常
點贊
收藏

51CTO技術棧公眾號

精品高清视频| 久久久久久久久久久av| 久久婷五月综合| 日本在线观看网站| 国产综合色精品一区二区三区| xxxxx91麻豆| 色欲欲www成人网站| 鲁鲁在线中文| 亚洲国产精品99久久久久久久久 | 久久99精品久久久久久久久久| 久久久久亚洲av成人毛片韩| 日本福利片在线| 久久九九免费| 久久久av亚洲男天堂| 国产情侣久久久久aⅴ免费| 成人小电影网站| 中文字幕一区二区5566日韩| 精品欧美一区二区久久久伦 | av在线资源网| 国产成人亚洲综合a∨婷婷 | 亚洲成人精品在线| 浓精h攵女乱爱av| 欧美日韩在线视频免费观看| 久久婷婷久久一区二区三区| 91在线国产电影| 亚洲欧美综合另类| 欧美a级片网站| 永久免费毛片在线播放不卡| 日韩大尺度视频| 国产经典一区| 污片在线观看一区二区| 中日韩在线视频| 天堂av在线免费观看| 国产一区不卡在线| 国产精品高潮呻吟久久av无限| 久久婷婷一区二区| 日韩欧美中文| 亚洲欧美制服综合另类| 久久久男人的天堂| 亚洲伊人伊成久久人综合网| 欧美在线一二三| 久色视频在线播放| 青春草在线视频| 国产精品看片你懂得| 欧洲在线视频一区| 香蕉av在线播放| 懂色av中文字幕一区二区三区| 国产日本欧美一区二区三区在线| 91午夜精品亚洲一区二区三区| 黄色亚洲大片免费在线观看| 久久久久999| 91视频最新网址| 国内成人精品| 亚洲另类激情图| 国产伦精品一区二区三区精品| 国产精品亚洲欧美日韩一区在线 | 樱花视频在线免费观看| 亚洲精品孕妇| 久久久久久国产免费| 全程偷拍露脸中年夫妇| 91精品国产乱码久久久久久久| 在线精品国产欧美| 国产伦精品一区二区三区视频女| 亚洲国产合集| 亚洲欧美日韩网| 加勒比精品视频| 天堂资源在线亚洲| 精品视频久久久| 久久精品老司机| 思热99re视热频这里只精品| 亚洲精品视频二区| 国产熟妇搡bbbb搡bbbb| 久久93精品国产91久久综合| 亚洲欧洲中文天堂| 国产成人免费观看网站| 日韩aaaa| 美女黄色丝袜一区| 欧美日韩一区二区三| 成人黄色片视频| 蜜桃视频在线观看播放| 欧美日韩在线一区| 虎白女粉嫩尤物福利视频| 色成人免费网站| 欧美日韩亚洲综合在线| 黄色一级片免费播放| 伊人www22综合色| 精品国产乱子伦一区| 人妻丰满熟妇av无码久久洗澡 | 特级黄色片视频| 中文字幕成人| 蜜桃传媒麻豆第一区在线观看| 欧美日韩你懂的| 99日在线视频| 99ri日韩精品视频| 日韩精品在线看| 小早川怜子久久精品中文字幕| 国产区精品区| 久久精品视频在线播放| 免费在线一级片| 新67194成人永久网站| 国产精品久久久久秋霞鲁丝| 国产又粗又猛视频免费| 成人免费视频一区| 婷婷久久伊人| 欧美v亚洲v| 色成年激情久久综合| 亚洲涩涩在线观看| 精品综合久久88少妇激情| 国产亚洲欧洲高清| 免费在线视频观看| 免费成人你懂的| 国产精品中出一区二区三区| 在线看黄色av| 午夜视频一区在线观看| 国产探花在线看| 精品五月天堂| 久久久www成人免费精品| 国产成人免费观看视频 | 98精品在线视频| 精品国产三级a在线观看| 日韩 国产 一区| 日韩在线麻豆| 欧美黑人xxxⅹ高潮交| 欧美一级做a爰片免费视频| 国产成人av网站| 亚洲黄色成人久久久| www.色在线| 宅男在线国产精品| 人妻少妇无码精品视频区| 在线看片欧美| 91天堂在线视频| 成人性生交大片免费看午夜| 亚洲成人精品影院| 一级片免费在线观看视频| 精品视频黄色| 欧美综合在线第二页| 丰满熟妇乱又伦| 亚洲色图19p| 黄色手机在线视频| 久草在线成人| 青青草一区二区| 日本xxxx人| 亚洲一区二区欧美| 日本55丰满熟妇厨房伦| 日本а中文在线天堂| 制服丝袜中文字幕一区| www久久久久久久| 日韩精品电影一区亚洲| 色综合久久66| 国产三级中文字幕| 精品九九久久| 中文字幕日韩综合av| 欧美一区二区三区网站| 2014亚洲片线观看视频免费| 欧美日韩一道本| 欧美性生活一级片| 性色av一区二区三区红粉影视| 黄色av免费观看| 亚洲主播在线观看| 中国男女全黄大片| 在线欧美视频| 国产精品日韩一区二区免费视频| 日韩少妇视频| 精品剧情在线观看| 国产精品成人国产乱| www.亚洲色图.com| 成熟了的熟妇毛茸茸| 欧美一级三级| 日韩女优人人人人射在线视频| 日韩有码电影| 91久久精品网| 91麻豆精品国产91久久综合| 日本不卡一二三区黄网| 亚洲国产日韩综合一区| 99精品国产九九国产精品| 久久精品国产一区二区电影| 国产三级伦理片| 一区二区三区波多野结衣在线观看| 在线观看免费视频污| 欧美精品麻豆| 狠狠色噜噜狠狠色综合久| 亚洲最大成人| 色伦专区97中文字幕| a级片在线免费看| 亚洲成av人在线观看| 波多野吉衣中文字幕| 美腿丝袜在线亚洲一区| 特级西西444| 欧美中文一区| 国产欧美一区二区三区久久| 91福利国产在线观看菠萝蜜| 亚洲成人久久一区| 成人黄色三级视频| 亚洲欧美日韩电影| 激情综合丁香五月| 麻豆国产精品777777在线| 精品免费久久久久久久| 精品在线网站观看| 国产精品一区二区三区在线播放 | av日韩亚洲| 一本一本久久a久久精品综合小说| 国产伦精品一区二区三区免.费| 亚洲国产精品欧美一二99| 国产在线综合视频| 国产99久久久国产精品免费看 | 亚洲一区电影在线观看| 99精品桃花视频在线观看| 成人性视频欧美一区二区三区| 综合一区av| 欧美午夜精品久久久久免费视| 四虎影视精品永久在线观看| 97精品久久久中文字幕免费| 91福利在线视频| 亚洲精品720p| 国产精品亚洲lv粉色| 欧美午夜激情在线| 欧美精品一级片| 国产性天天综合网| 扒开伸进免费视频| 精品一区二区三区在线播放视频| 我的公把我弄高潮了视频| 999国产精品永久免费视频app| 国模一区二区三区私拍视频| 国产精品3区| 国产97在线|亚洲| 99在线视频影院| 久久精品视频在线| h视频网站在线观看| 亚洲国产欧美一区二区丝袜黑人| 国产日韩欧美视频在线观看| 欧美在线不卡一区| 国产免费av一区| 亚洲h在线观看| 国产av 一区二区三区| 国产精品福利影院| av手机在线播放| 久久蜜桃一区二区| 亚洲AV无码国产精品| 成人性视频网站| 99热这里只有精品2| 美女视频第一区二区三区免费观看网站 | 国内精品久久久久影院优| 麻豆系列在线观看| 色av中文字幕一区| 啊v视频在线| 亚洲日韩欧美视频一区| 日韩午夜影院| 日韩av在线一区| 四虎免费在线观看| 亚洲国产日韩欧美在线99| 性生活免费网站| 精品日韩在线观看| 国产成人a人亚洲精品无码| 欧美久久久久久蜜桃| 69xxxx国产| 日本精品视频一区二区三区| 日韩 国产 欧美| 91国产福利在线| 无码人妻丰满熟妇精品| 色综合欧美在线| 在线免费观看国产精品| 色欧美日韩亚洲| 国产精品尤物视频| 欧美特级限制片免费在线观看| 欧美日韩 一区二区三区| 欧美日韩一区二区三区在线| 在线观看国产小视频| 欧美日韩日日夜夜| 国产人妻精品一区二区三区| 欧美变态凌虐bdsm| 无码精品视频一区二区三区| 亚洲男人天堂2023| av免费观看一区二区| 精品国产欧美成人夜夜嗨| av网站在线看| 久久久久久伊人| 人人草在线视频| 国产精品h片在线播放| 亚洲欧美久久精品| 97国产超碰| 天堂成人娱乐在线视频免费播放网站 | 久久精品人妻一区二区三区| 亚洲成av人片在线| 久久久免费高清视频| 欧美亚日韩国产aⅴ精品中极品| 一级做a爱片性色毛片| 日韩一级黄色大片| 亚洲色大成网站www| 国产一区二区久久精品| 乱人伦中文视频在线| 欧美精品videos另类日本| 欧美国产大片| 91在线色戒在线| 任你弄精品视频免费观看| 日韩在线三级| 黄色成人在线网站| 另类小说第一页| 国产成人av电影免费在线观看| v8888av| 亚洲黄色尤物视频| av手机天堂网| 日韩精品在线网站| bbbbbbbbbbb在线视频| 欧美丰满少妇xxxxx| 欧美日韩免费观看视频| 97se在线视频| 青青草国产免费一区二区下载| 国产资源第一页| 男女激情视频一区| 国产精品无码一区二区三| 国产精品久久久久久户外露出| 日韩av综合在线| 欧美日韩国产综合一区二区三区| 人妻偷人精品一区二区三区| 中文字幕视频在线免费欧美日韩综合在线看| 3d玉蒲团在线观看| 国产精品久久久久久久久免费看| 懂色av一区二区| 久久久成人精品一区二区三区| 久久一二三四| 美女露出粉嫩尿囗让男人桶| 一区在线播放视频| 国产情侣小视频| 亚洲精品动漫100p| 99热国产在线中文| 国产欧美亚洲精品| 一区二区三区日本久久久| 国产免费一区二区视频| 国产九色精品成人porny| 夜夜春很很躁夜夜躁| 色综合激情五月| 天堂在线免费av| 91精品国产网站| 大陆精大陆国产国语精品| 制服丝袜综合日韩欧美| 日韩精品亚洲一区二区三区免费| 少妇饥渴放荡91麻豆| 亚洲午夜羞羞片| 亚洲av无码专区在线| 欧美成年人视频网站| 亚洲一区二区小说| 黄频视频在线观看| 另类综合日韩欧美亚洲| 国产视频不卡在线| 在线免费不卡电影| 91在线看片| 国产精品亚洲欧美导航| 欧美精品尤物在线观看| 成年人视频在线免费| 99久久精品99国产精品| 久久夜靖品2区| 亚洲大尺度美女在线| gogo高清午夜人体在线| 国产精品福利视频| 欧美午夜久久| 9.1在线观看免费| 一二三区精品福利视频| www.热久久| 欧美激情中文字幕乱码免费| 秋霞影院一区| 欧美一二三不卡| 懂色av一区二区夜夜嗨| 国产精品 欧美 日韩| 亚洲娇小xxxx欧美娇小| 天天综合网站| 亚洲 国产 日韩 综合一区| 蜜桃精品视频在线| 99鲁鲁精品一区二区三区| 欧美日韩的一区二区| av在线导航| 国产精品一级久久久| 午夜亚洲激情| 亚洲区免费视频| 欧美日韩另类一区| 日韩精品卡一| 免费精品视频一区二区三区| 久久精品一区| 自拍偷拍你懂的| 日韩欧美在线不卡| 九色porny丨入口在线| 日韩福利影院| 国产一区二区三区黄视频 | 欧美激情高清视频| 日韩欧美天堂| 免费涩涩18网站入口| 亚洲男女一区二区三区| 少妇一级淫片免费看| 午夜精品久久久久久久男人的天堂| 精品一区二区三区中文字幕在线| 国产黄色激情视频| 久久美女高清视频| 国产精品天天操| 欧美亚洲午夜视频在线观看| 久久综合国产| 无码人妻精品一区二区三| 在线观看中文字幕不卡| 国产精品久久麻豆| 久久大片网站| 韩国三级电影一区二区| 中文字幕一区二区三区手机版|