最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Golang中NewTimer計(jì)時(shí)器的底層實(shí)現(xiàn)原理

 更新時(shí)間:2023年05月04日 10:48:49   作者:starrySky  
本文將主要介紹一下Go語(yǔ)言中的NewTimer,首先展示基于NewTimer創(chuàng)建的定時(shí)器來實(shí)現(xiàn)超時(shí)控制。接著通過一系列問題的跟進(jìn),展示了NewTimer的底層實(shí)現(xiàn)原理,需要的可以參考一下

1.簡(jiǎn)介

本文將介紹 Go 語(yǔ)言中的NewTimer,首先展示基于NewTimer創(chuàng)建的定時(shí)器來實(shí)現(xiàn)超時(shí)控制。接著通過一系列問題的跟進(jìn),展示了NewTimer的底層實(shí)現(xiàn)原理。

2.基本使用

我們首先通過一個(gè)簡(jiǎn)單的例子,來展示是怎么基于NewTimer實(shí)現(xiàn)超時(shí)控制的。

假設(shè)有一個(gè)需求,要求在 5 秒鐘內(nèi)完成某個(gè)任務(wù),否則就認(rèn)為任務(wù)失敗。這時(shí)我們就可以使用 NewTimer 來實(shí)現(xiàn)超時(shí)控制。具體的實(shí)現(xiàn)步驟如下:

  • 首先,基于NewTimer創(chuàng)建一個(gè) Timer 對(duì)象,設(shè)定超時(shí)時(shí)間為 5 秒鐘。
  • 然后,啟動(dòng)一個(gè) goroutine 來執(zhí)行任務(wù),并在任務(wù)完成后向通道發(fā)送一個(gè)完成信號(hào)。
  • 最后,使用 select 語(yǔ)句等待 Timer 的到期事件或任務(wù)完成信號(hào),如果 Timer 先到期,就認(rèn)為任務(wù)超時(shí)了,否則就認(rèn)為任務(wù)完成了。

下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)代碼展示:

package main

import (
        "fmt"
        "time"
)

func main() {
        // 創(chuàng)建一個(gè)定時(shí)器,超時(shí)時(shí)間為 5 秒鐘
        timer := time.NewTimer(5 * time.Second)

        // 啟動(dòng)一個(gè) goroutine 執(zhí)行任務(wù),并在任務(wù)完成后向通道發(fā)送一個(gè)完成信號(hào)
        done := make(chan bool, 1)
        go func() {
                // 模擬任務(wù)執(zhí)行耗時(shí)
                time.Sleep(2 * time.Second)
                done <- true
        }()

        // 等待任務(wù)完成或者超時(shí)
        select {
        case <-done:
                // 任務(wù)完成,輸出完成信息
                fmt.Println("Task finished.")
        case <-timer.C:
                // 超時(shí),輸出超時(shí)信息
               fmt.Println("Task timed out.")
        }
}

在上述代碼中,我們首先使用NewTimer創(chuàng)建了一個(gè)time.Timer對(duì)象,超時(shí)時(shí)間為 5 秒鐘。然后啟動(dòng)一個(gè) goroutine 來執(zhí)行任務(wù),并在任務(wù)完成后向通道 done 發(fā)送一個(gè)完成信號(hào)。最后使用 select 語(yǔ)句等待任務(wù)完成信號(hào)或者Timer的到期事件,如果Timer先到期,就認(rèn)為任務(wù)超時(shí)了,否則就認(rèn)為任務(wù)完成了。 在運(yùn)行上述代碼時(shí),我們可以看到,在任務(wù)完成前 5 秒鐘內(nèi),程序輸出如下信息:

Task finished.

如果將任務(wù)完成時(shí)間改為超過 5 秒鐘,程序?qū)?huì)在 5 秒鐘后超時(shí),輸出如下信息:

Task timed out.

通過這個(gè)簡(jiǎn)單的例子,我們可以看到,如果任務(wù)在指定超時(shí)時(shí)間內(nèi)完成,此時(shí)會(huì)執(zhí)行正常的業(yè)務(wù)邏輯;如果任務(wù)未在指定的超時(shí)時(shí)間內(nèi)完成,此時(shí)將走執(zhí)行超時(shí)邏輯。

通過上述程序演示,我們展示了如何使用NewTimer創(chuàng)建的 time.Timer 實(shí)現(xiàn)超時(shí)控制的基本方法。

3.實(shí)現(xiàn)原理

3.1 內(nèi)容分析

回顧上面的示例代碼,我們實(shí)現(xiàn)超時(shí)控制的主要機(jī)制,是通過select語(yǔ)句同時(shí)監(jiān)聽兩個(gè)channel,一個(gè)是任務(wù)執(zhí)行狀態(tài)的channel,一個(gè)是定時(shí)器的channel。

當(dāng)任務(wù)執(zhí)行完成時(shí),便通過channel對(duì)主協(xié)程進(jìn)行通知。當(dāng)定時(shí)器到達(dá)我們指定的時(shí)間,也就是超時(shí)時(shí)間,此時(shí)也通過定時(shí)器的channel進(jìn)行通知。

 同時(shí)監(jiān)聽這兩個(gè)channel,如果任務(wù)先執(zhí)行完成,此時(shí)將會(huì)走select語(yǔ)句中正常業(yè)務(wù)邏輯case的代碼,如果是在到達(dá)預(yù)定時(shí)間,任務(wù)仍沒有完成,此時(shí)通過定時(shí)器channel進(jìn)行通知,從而走超時(shí)業(yè)務(wù)邏輯case的代碼,從而實(shí)現(xiàn)超時(shí)控制。

因此,這里主要的問題是,是如何在到達(dá)超時(shí)時(shí)間時(shí),準(zhǔn)時(shí)往定時(shí)器中的C對(duì)應(yīng)的channel發(fā)送送數(shù)據(jù),從而來告知其他協(xié)程,已經(jīng)到達(dá)超時(shí)時(shí)間了呢,這個(gè)是如何做到的呢?

3.2 基本思路

下面先來看看NewTimer方法返回Timer結(jié)構(gòu)體的內(nèi)容,定義如下:

type Timer struct {
   C <-chan Time
   r runtimeTimer
}

可以看到,Timer結(jié)構(gòu)體中C是一個(gè)chan Time類型的變量。在前面的代碼的例子中,select語(yǔ)句是監(jiān)聽Timer結(jié)構(gòu)體中的C變量,從中來讀取數(shù)據(jù)的。

那么,當(dāng)?shù)竭_(dá)超時(shí)時(shí)間時(shí),TimerC對(duì)應(yīng)的channel將會(huì)有數(shù)據(jù)到達(dá),那么肯定有其他地方,在到達(dá)超時(shí)時(shí)間時(shí),會(huì)往Timer中的C發(fā)送數(shù)據(jù)。

那么現(xiàn)在的主要問題,是怎么做到當(dāng)?shù)竭_(dá)指定時(shí)間時(shí),往Timer中的C發(fā)送數(shù)據(jù)呢?

其實(shí),在go語(yǔ)言中,存在這樣一個(gè)運(yùn)行時(shí)函數(shù)startTimer ,定義如下:

func startTimer(*runtimeTimer)

它的作用是啟動(dòng)一個(gè)定時(shí)器,當(dāng)定時(shí)器到期時(shí),會(huì)執(zhí)行相應(yīng)的回調(diào)函數(shù)并傳遞回調(diào)參數(shù)。在 startTimer 函數(shù)內(nèi)部,會(huì)使用系統(tǒng)調(diào)用來啟動(dòng)一個(gè)底層的操作系統(tǒng)定時(shí)器,等到定時(shí)器超時(shí)時(shí),底層系統(tǒng)會(huì)自動(dòng)觸發(fā)一個(gè)信號(hào)(例如 Unix 平臺(tái)上的 SIGALRM 信號(hào)),然后該信號(hào)將由 Go 運(yùn)行時(shí)內(nèi)部的信號(hào)處理函數(shù)捕獲,并最終調(diào)用相關(guān)的回調(diào)函數(shù)。

那么,這里我們似乎可以使用startTimer來實(shí)現(xiàn),當(dāng)?shù)竭_(dá)指定時(shí)間時(shí),往channel發(fā)送數(shù)據(jù),從而達(dá)到通知其他協(xié)程的效果。

3.3 實(shí)現(xiàn)步驟

首先,我們已經(jīng)知道,startTimer能夠啟動(dòng)一個(gè)定時(shí)器,當(dāng)定時(shí)器到期時(shí),會(huì)執(zhí)行相應(yīng)的回調(diào)函數(shù)并傳遞回調(diào)參數(shù)。而定時(shí)器的到期時(shí)間、回調(diào)函數(shù)以及回調(diào)函數(shù)的參數(shù),則是通過runtimeTimer結(jié)構(gòu)體傳遞過去的。

下面我們只需要runtimeTimer字段的含義,然后根據(jù)其含義,正確設(shè)置runtimeTimer結(jié)構(gòu)體字段,調(diào)用startTimer方法啟動(dòng)一個(gè)定時(shí)器,就能夠?qū)崿F(xiàn)在指定時(shí)間時(shí),執(zhí)行某段邏輯。下面我們來看看runtimeTime的定義:

type runtimeTimer struct {
   pp       uintptr
   when     int64
   period   int64
   f        func(any, uintptr) // NOTE: must not be closure
   arg      any
   seq      uintptr
   nextwhen int64
   status   uint32
}

下面對(duì)runtimeTimer中的字段進(jìn)行說明:

  • when int64:表示定時(shí)器應(yīng)該在何時(shí)觸發(fā)。該值的單位是納秒
  • period int64:表示定時(shí)器的重復(fù)周期。如果定時(shí)器不需要重復(fù)觸發(fā),則該值為 0
  • f func(any, uintptr):指向定時(shí)器到期后需要執(zhí)行的函數(shù)。
  • arg any:表示傳遞給定時(shí)器到期后執(zhí)行的函數(shù)的參數(shù),將傳遞給f的第一個(gè)參數(shù)
  • nextwhen int64:如果定時(shí)器是重復(fù)觸發(fā)的,則 nextwhen 表示下一次觸發(fā)的時(shí)間。
  • seq uintptr:用于防止定時(shí)器被錯(cuò)誤的重置。當(dāng)定時(shí)器被重置時(shí),seq 會(huì)被更新。

基于對(duì)上面字段含義的理解,此時(shí)我們定義一個(gè)runtimeTimer結(jié)構(gòu)體,然后調(diào)用startTimer,從而來實(shí)現(xiàn)能夠在指定的某個(gè)時(shí)間點(diǎn),往某個(gè)channel發(fā)送數(shù)據(jù)。具體實(shí)現(xiàn)如下:

// 定義一個(gè)channel,用于發(fā)送數(shù)據(jù)
c := make(chan Time, 1)
r := runtimeTimer{
      // 指定超時(shí)時(shí)間戳
      when: when(d),
      // 指定回調(diào)函數(shù)
      f: func sendTime(c any, seq uintptr) {
               select {
               case c.(chan Time) <- Now():
               default:
              }
        },
      // 傳遞給回調(diào)函數(shù)的參數(shù)
      arg:  c,
   },
}
// 調(diào)用startTimer啟動(dòng)一個(gè)定時(shí)器
startTimer(&t.r)

首先會(huì)創(chuàng)建一個(gè)帶有緩沖的通道 c。

接著初始化runtimeTimer結(jié)構(gòu)體的值,設(shè)定好超時(shí)時(shí)間,回調(diào)函數(shù)以及參數(shù)。超時(shí)時(shí)間使用的是when函數(shù)來獲取計(jì)數(shù)器的結(jié)束時(shí)間。when 函數(shù)會(huì)根據(jù)給定的時(shí)間間隔 d,返回一個(gè)絕對(duì)時(shí)間點(diǎn),即計(jì)時(shí)器結(jié)束時(shí)間。

f字段指定的回調(diào)函數(shù),則是將當(dāng)前時(shí)間 Now() 發(fā)送到通道 c 中。當(dāng)?shù)竭_(dá)指定超時(shí)時(shí)間時(shí),其將會(huì)調(diào)用回調(diào)函數(shù)f,同時(shí)將runtimeTimer結(jié)構(gòu)體中arg字段的值,作為參數(shù)傳遞到回調(diào)函數(shù)當(dāng)中。

然后調(diào)用startTimer啟動(dòng)一個(gè)定時(shí)器。當(dāng)?shù)竭_(dá)超時(shí)時(shí)間,將會(huì)調(diào)用回調(diào)函數(shù),回調(diào)函數(shù)其會(huì)往一開始定義的channel發(fā)送數(shù)據(jù)。

至此,我們實(shí)現(xiàn)了最開始提到的,當(dāng)?shù)竭_(dá)指定時(shí)間時(shí),往Timer中的C發(fā)送數(shù)據(jù)這個(gè)任務(wù)。

3.4 NewTimer的實(shí)現(xiàn)

回到我們的題目,NewTimer計(jì)時(shí)器的底層實(shí)現(xiàn)原理是什么?事實(shí)上,NewTimer創(chuàng)建的定時(shí)器,也確實(shí)是基于startTimer來實(shí)現(xiàn)的,下面我們來看看其實(shí)現(xiàn):

func NewTimer(d Duration) *Timer {
   c := make(chan Time, 1)
   t := &Timer{
      C: c,
      r: runtimeTimer{
         when: when(d),
         f:    sendTime,
         arg:  c,
      },
   }
   startTimer(&t.r)
   return t
}

首先會(huì)創(chuàng)建一個(gè)帶有緩沖的通道 c。然后創(chuàng)建一個(gè) Timer 對(duì)象 t,將 c 通道賦值給 tC 屬性。channel之后將作為回調(diào)函數(shù)的參數(shù),同時(shí)也會(huì)作為Timer對(duì)象中C屬性的值。這樣子回調(diào)函數(shù)和Timer結(jié)構(gòu)體中C變量與回調(diào)函數(shù)的channel事實(shí)上是共用一個(gè)channel的。

runtimeTimer結(jié)構(gòu)體中的回調(diào)函數(shù)sendTime的實(shí)現(xiàn)與之前講述的并無差異,都是將當(dāng)前時(shí)間 Now() 發(fā)送到通道中,這里將不再贅述。

Timer結(jié)構(gòu)體中C變量與回調(diào)函數(shù)的channel事實(shí)上是共用一個(gè)channel的,當(dāng)?shù)竭_(dá)超時(shí)時(shí)間,則會(huì)執(zhí)行回調(diào)函數(shù),往channel發(fā)送數(shù)據(jù)。而通過select語(yǔ)句對(duì)Timer中的channel進(jìn)行監(jiān)聽的協(xié)程,此時(shí)也正常接收到通知了。

4.總結(jié)

在這篇文章中,我們首先展示了使用NewTimer創(chuàng)建一個(gè)定時(shí)器,然后基于此實(shí)現(xiàn)超時(shí)控制。我們發(fā)現(xiàn),比較重要的一個(gè)機(jī)制是,timer對(duì)象是在到達(dá)超時(shí)時(shí)間時(shí),timer對(duì)象中C對(duì)應(yīng)的channel將會(huì)接收到數(shù)據(jù)。

timer對(duì)象在達(dá)到超時(shí)時(shí)間時(shí),C屬性對(duì)應(yīng)的channel便能夠接收到數(shù)據(jù),這個(gè)是怎么做到的呢? 我們基于此進(jìn)行了分析,事實(shí)上,首先是基于startTimer創(chuàng)建定時(shí)器,同時(shí)runtimeTimer結(jié)構(gòu)體指定了回調(diào)函數(shù),從而實(shí)現(xiàn)達(dá)到超時(shí)時(shí)間時(shí),回調(diào)函數(shù)往C屬性對(duì)應(yīng)的channel發(fā)送數(shù)據(jù)。然后就能夠基于該特性,能夠?qū)崿F(xiàn)超時(shí)控制等機(jī)制。

到此這篇關(guān)于詳解Golang中NewTimer計(jì)時(shí)器的底層實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)Golang NewTimer計(jì)時(shí)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于Go語(yǔ)言中的IO操作詳解

    關(guān)于Go語(yǔ)言中的IO操作詳解

    在現(xiàn)代軟件開發(fā)中,高效的輸入輸出(I/O)操作是提高程序性能的關(guān)鍵之一,Go語(yǔ)言提供了豐富的I/O操作接口,使得文件讀寫、網(wǎng)絡(luò)通信等任務(wù)變得簡(jiǎn)單而高效,本文介紹了關(guān)于Go語(yǔ)言中的IO操作,需要的朋友可以參考下
    2024-10-10
  • Golang實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)Stack(堆棧)的示例詳解

    Golang實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)Stack(堆棧)的示例詳解

    在計(jì)算機(jī)科學(xué)中,stack(棧)是一種基本的數(shù)據(jù)結(jié)構(gòu),它是一種線性結(jié)構(gòu),具有后進(jìn)先出(Last In First Out)的特點(diǎn)。本文將通過Golang實(shí)現(xiàn)堆棧,需要的可以參考一下
    2023-04-04
  • go依賴注入管理工具wire的使用方法

    go依賴注入管理工具wire的使用方法

    本文主要介紹了如何使用go wire管理依賴,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • Go語(yǔ)言設(shè)置JSON的默認(rèn)值操作

    Go語(yǔ)言設(shè)置JSON的默認(rèn)值操作

    這篇文章主要介紹了Go語(yǔ)言設(shè)置JSON的默認(rèn)值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang HTML 模板使用指南示例詳解

    Golang HTML 模板使用指南示例詳解

    本文詳細(xì)介紹了Golang HTML模板的使用方法,包括基礎(chǔ)模板、高級(jí)模板、完整應(yīng)用示例、CSS樣式、JavaScript交互等,文章強(qiáng)調(diào)了模板組織、代碼復(fù)用、語(yǔ)義化HTML、響應(yīng)式設(shè)計(jì)、性能優(yōu)化等最佳實(shí)踐,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • Go項(xiàng)目實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)與平滑重啟功能

    Go項(xiàng)目實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)與平滑重啟功能

    無論是優(yōu)雅關(guān)機(jī)還是優(yōu)雅重啟歸根結(jié)底都是通過監(jiān)聽特定系統(tǒng)信號(hào),然后執(zhí)行一定的邏輯處理保障當(dāng)前系統(tǒng)正在處理的請(qǐng)求被正常處理后再關(guān)閉當(dāng)前進(jìn)程,這篇文章主要介紹了Go實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)與平滑重啟 ,需要的朋友可以參考下
    2022-10-10
  • Go實(shí)現(xiàn)將任何網(wǎng)頁(yè)轉(zhuǎn)化為PDF

    Go實(shí)現(xiàn)將任何網(wǎng)頁(yè)轉(zhuǎn)化為PDF

    在許多應(yīng)用場(chǎng)景中,可能需要將網(wǎng)頁(yè)內(nèi)容轉(zhuǎn)化為?PDF?格式,使用Go編程語(yǔ)言,結(jié)合一些現(xiàn)有的庫(kù),可以非常方便地實(shí)現(xiàn)這一功能,下面我們就來看看具體實(shí)現(xiàn)方法吧
    2024-11-11
  • 舉例講解Go語(yǔ)言中函數(shù)的閉包使用

    舉例講解Go語(yǔ)言中函數(shù)的閉包使用

    這篇文章主要介紹了Go語(yǔ)言中函數(shù)的閉包使用示例,函數(shù)閉包c(diǎn)losure是編程語(yǔ)言中十分重要的特性,需要的朋友可以參考下
    2016-03-03
  • Go語(yǔ)言中進(jìn)行API限流的實(shí)戰(zhàn)詳解

    Go語(yǔ)言中進(jìn)行API限流的實(shí)戰(zhàn)詳解

    API?限流是控制和管理應(yīng)用程序訪問量的重要手段,旨在防止惡意濫用、保護(hù)后端服務(wù)的穩(wěn)定性和可用性,下面我們就來看看如何在Go語(yǔ)言中具體實(shí)現(xiàn)吧
    2025-01-01
  • 詳解golang 定時(shí)任務(wù)time.Sleep和time.Tick實(shí)現(xiàn)結(jié)果比較

    詳解golang 定時(shí)任務(wù)time.Sleep和time.Tick實(shí)現(xiàn)結(jié)果比較

    本文主要介紹了golang 定時(shí)任務(wù)time.Sleep和time.Tick實(shí)現(xiàn)結(jié)果比較,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論

平邑县| 铁岭县| 临高县| 故城县| 西峡县| 东安县| 疏附县| 苗栗市| 汶上县| 灌云县| 太原市| 平昌县| 威信县| 昌邑市| 河间市| 临高县| 伊吾县| 宁津县| 百色市| 沙河市| 三门峡市| 都昌县| 汾阳市| 阜宁县| 镇江市| 上虞市| 瑞丽市| 大渡口区| 疏勒县| 称多县| 定西市| 宁蒗| 喀什市| 黔西| 南澳县| 璧山县| 集贤县| 顺平县| 共和县| 海兴县| 广德县|