欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang實(shí)現(xiàn)協(xié)程超時(shí)控制的方式總結(jié)

 更新時(shí)間:2023年05月24日 10:31:49   作者:tracy小貓  
我們知道,go協(xié)程如果不做好處理,很容易造成內(nèi)存泄漏,所以對goroutine做超時(shí)控制,才能有效避免這種情況發(fā)生,本文為大家整理了兩個(gè)常見的Golang超時(shí)控制方法,需要的可以收藏一下

Golang對協(xié)程做超時(shí)的控制大概有兩種方式,timer 和context。對于并發(fā)情況,又有不同的方式。

我們知道,go協(xié)程如果不做好處理,很容易造成內(nèi)存泄漏。特別是在高并發(fā)的情況下,如果某一個(gè) goroutine 由于意外退出,則會(huì)導(dǎo)致接收方一直阻塞,從而掛起主程序。

對goroutine做超時(shí)控制,能夠有效避免這種情況發(fā)生。

Timer+Select

time.After 實(shí)現(xiàn)超時(shí)控制

  • 利用 time.After 啟動(dòng)了一個(gè)異步的定時(shí)器,返回一個(gè) channel,當(dāng)超過指定的時(shí)間后,該 channel 將會(huì)接受到信號(hào)。
  • 啟動(dòng)了子協(xié)程,函數(shù)執(zhí)行結(jié)束后,將向 channel ch 發(fā)送結(jié)束信號(hào)。
  • 使用 select 阻塞等待 done 或 time.After 的信息,若超時(shí),輸出timeout,若沒有超時(shí),則輸出done。
func TestContext12(t *testing.T) {
    ch := make(chan struct{}, 1)
    go func() {
       fmt.Println("running...")
       time.Sleep(3 * time.Second)
       ch <- struct{}{}
   }()
    select {
       case <-ch:
       fmt.Println("done")
       case <-time.After(2 * time.Second):
       fmt.Println("timeout")
   }
}

output:

=== RUN   TestContext12
running...
timeout
--- PASS: TestContext12 (3.01s)
PASS

這里要注意一個(gè)點(diǎn),就是你創(chuàng)建ch 的時(shí)候,必須是帶緩沖的。如果不帶,在并發(fā)的情況下會(huì)怎樣呢?

NewTimer

也可以新建一個(gè)NewTimer,timer.C返回也是一個(gè)channel

func TestContext5(t *testing.T) {
   timer := time.NewTimer(time.Duration(time.Millisecond * 900))
   ch := make(chan struct{}, 1)
   go func() {
      fmt.Println("running...")
      time.Sleep(3 * time.Second)
      ch <- struct{}{}
   }()
   select {
   case <-ch:
      fmt.Println("done")
   case <-timer.C:
      fmt.Println("timeout")
   }
}

output:

=== RUN   TestContext5
running...
timeout
--- PASS: TestContext5 (0.90s)
PASS

留一個(gè)坑

為什么不需要關(guān)閉ch 管道?什么時(shí)候關(guān)閉ch?

Context+Select

  • 第二種方案是利用 context,context.WithTimeout。
  • 它接受一個(gè)Context和一個(gè)超時(shí)時(shí)間作為參數(shù),返回一個(gè)子Context和一個(gè)取消函數(shù)CancelFunc。
  • 取消函數(shù)CancelFunc將釋放子Context與之有關(guān)的資源,因此在子Context中的相關(guān)操作一旦完成,應(yīng)該立即調(diào)用取消函數(shù)CancelFunc。
func TestContext6(t *testing.T) {
   ch := make(chan string)
   timeout, cancel := context.WithTimeout(context.Background(), 2*time.Second)
   defer cancel()
   go func() {
      time.Sleep(time.Second * 3)
      ch <- "done"
   }()
   select {
   case res := <-ch:
      fmt.Println(res)
   case <-timeout.Done():
      fmt.Println("timout", timeout.Err())
   }
}
  • 利用 context.WithTimeou 返回啟動(dòng)了一個(gè)異步的定時(shí)器,返回一個(gè) channel,當(dāng)超過指定的時(shí)間后,該 channel 將會(huì)接受到信號(hào)。
  • 啟動(dòng)了子協(xié)程,函數(shù)執(zhí)行結(jié)束后,將向 channel ch 發(fā)送結(jié)束信號(hào)。
  • 使用 select 阻塞等待 done 或 time.Done的信息,若超時(shí),輸出timeout,若沒有超時(shí),則輸出done。

output:

=== RUN   TestContext6
timout context deadline exceeded
--- PASS: TestContext6 (2.00s)
PASS

context+并發(fā)協(xié)程

并發(fā)協(xié)程使用WaitGroup阻塞主協(xié)程保證生產(chǎn)協(xié)程和消費(fèi)協(xié)程正常執(zhí)行完成。

func TestContext3(t *testing.T) {
   withTimeout, cancelFunc := context.WithTimeout(context.Background(), time.Second*1)
   waitGroup := sync.WaitGroup{}
   waitGroup.Add(2)
   go func() { //協(xié)程1
      time.Sleep(time.Second)
      fmt.Println("finished 1")
      waitGroup.Done()
   }()
   go func() { //協(xié)程2
      time.Sleep(time.Second * 2)
      fmt.Println("finished 2")
      waitGroup.Done()
   }()
   go func() {
      select {
      case <-withTimeout.Done():
         fmt.Println("timeout")
         return
      default:
         waitGroup.Wait()
         cancelFunc()
         fmt.Println("finished all")
         return //結(jié)束監(jiān)聽協(xié)程
      }
   }()
   <-withTimeout.Done()
}
  • 開啟協(xié)程1,等待1秒輸出。協(xié)程2,等待2秒輸出。
  • context.WithTimeout等待1秒后返回函數(shù)。
  • 1秒后,協(xié)程一輸出。但是協(xié)程二沒輸出,主線程不等待了。直接返回。

output:

=== RUN   TestContext3
finished 1
--- PASS: TestContext3 (1.01s)
PASS

這里多一個(gè)問題,留個(gè)坑!

goroutine如何超時(shí)控制并發(fā)輸出a,b,c并且按照a,b,c的順序輸出?

到此這篇關(guān)于Golang實(shí)現(xiàn)協(xié)程超時(shí)控制的方式總結(jié)的文章就介紹到這了,更多相關(guān)Golang協(xié)程超時(shí)控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Golang如何優(yōu)雅判斷interface是否為nil

    詳解Golang如何優(yōu)雅判斷interface是否為nil

    這篇文章主要為大家詳細(xì)介紹了Golang如何優(yōu)雅判斷interface是否為nil的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解下
    2024-01-01
  • Go語言TCP從原理到代碼實(shí)現(xiàn)詳解

    Go語言TCP從原理到代碼實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了Go語言TCP從原理到代碼實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 一文搞懂Golang 時(shí)間和日期相關(guān)函數(shù)

    一文搞懂Golang 時(shí)間和日期相關(guān)函數(shù)

    這篇文章主要介紹了Golang 時(shí)間和日期相關(guān)函數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • golang http 連接超時(shí)和傳輸超時(shí)的例子

    golang http 連接超時(shí)和傳輸超時(shí)的例子

    今天小編就為大家分享一篇golang http 連接超時(shí)和傳輸超時(shí)的例子,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • Golang中Channel實(shí)戰(zhàn)技巧與一些說明

    Golang中Channel實(shí)戰(zhàn)技巧與一些說明

    channel是Go語言內(nèi)建的first-class類型,也是Go語言與眾不同的特性之一,下面這篇文章主要給大家介紹了關(guān)于Golang中Channel實(shí)戰(zhàn)技巧與一些說明的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • 簡單高效!Go語言封裝二級(jí)認(rèn)證功能實(shí)現(xiàn)

    簡單高效!Go語言封裝二級(jí)認(rèn)證功能實(shí)現(xiàn)

    本文將介紹如何使用Go語言封裝二級(jí)認(rèn)證功能,實(shí)現(xiàn)簡單高效的用戶認(rèn)證流程,二級(jí)認(rèn)證是一種安全措施,要求用戶在登錄后進(jìn)行額外的身份驗(yàn)證,以提高賬戶安全性,
    2023-10-10
  • go語言基礎(chǔ) seek光標(biāo)位置os包的使用

    go語言基礎(chǔ) seek光標(biāo)位置os包的使用

    這篇文章主要介紹了go語言基礎(chǔ) seek光標(biāo)位置os包的使用詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang中堆排序的實(shí)現(xiàn)

    Golang中堆排序的實(shí)現(xiàn)

    堆是一棵基于數(shù)組實(shí)現(xiàn)的特殊的完全二叉樹,本文主要介紹了Golang中堆排序的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Go語言遞歸函數(shù)的具體實(shí)現(xiàn)

    Go語言遞歸函數(shù)的具體實(shí)現(xiàn)

    本文主要介紹了Go語言遞歸函數(shù)的具體實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Go語言并發(fā)編程基礎(chǔ)上下文概念詳解

    Go語言并發(fā)編程基礎(chǔ)上下文概念詳解

    這篇文章主要為大家介紹了Go語言并發(fā)編程基礎(chǔ)上下文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評(píng)論