亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Web 應用程序中運行計劃任務

在 Web 應用程序中運行計劃任務

Go
MYYA 2023-07-17 14:53:02
我想每 5 分鐘運行一次任務來更新網站上的統計信息,而不阻塞 HTTP 服務器。我剛剛通過工作人員示例添加了基本的 HTTP 服務器邏輯。如果我添加了這樣的多個任務,這被認為是不好的做法還是有更好的方法?package mainimport (    "fmt"    "net/http"    "time")func Home(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "Home page")}func schedule(f func(), interval time.Duration) *time.Ticker {    ticker := time.NewTicker(interval)    go func() {        for range ticker.C {            f()        }    }()    return ticker}func longRunningTask() {    fmt.Println("Long running task")}func main() {    schedule(longRunningTask, time.Second*5)    http.HandleFunc("/", Home)    http.ListenAndServe("127.0.0.1:8080", nil)}
查看完整描述

1 回答

?
牧羊人nacy

TA貢獻1862條經驗 獲得超7個贊

您的實現與 Go 中的計劃作業/任務非常相似。有一些類似 cron 的庫可以讓您更好地控制任務,但在大多數情況下,帶有循環的簡單 goroutine 就足夠了。


以下是根據您的需求增加復雜性的更多示例:


永遠運行一個任務,每次運行之間等待 5 秒。無法停止并且不考慮任務的運行時間。這是最簡單的形式,也是最常見的形式。


go func() {

    for {

        task()

        <-time.After(5 * time.Second)

    }

}()

與以前相同,只是現在有一個通道可以在我們想要的時候停止任務。雖然您的實現允許您通過該方法停止任務Stop(),但 goroutine 將保持打開狀態,因為通道永遠不會關閉(因此會泄漏內存)。


// Includes a channel to stop the task if needed.

quit := make(chan bool, 1)


go func() {

    task()


    for {

        select {

        case <-quit:

            return

        case <-time.After(5 * time.Second):

            task()

        }

    }

}()


// To stop the task

quit <- true

這是三個解決方案中最強大的解決方案。任務可以隨時停止,并且它還會考慮任務在等待再次運行時所花費的時間。在前面的示例中,如果任務運行時間為 1 秒,而您又等待 5 秒,則相對于任務啟動時的時間間隔實際上是 6 秒。


該解決方案實際上僅適用于運行時間非常長的任務,或者如果您的任務以恒定的時間間隔運行至關重要。如果任務必須以恒定的時間間隔運行,那么您需要考慮到time.After()至少會等待您提供的持續時間的事實——如果 CPU 忙于其他進程/goroutines,它最終可能會等待稍長的時間。


// Calls `fn` and then waits so the total elapsed time is `interval`

func runAndWait(interval time.Duration, fn func()) {

    earlier := time.Now()

    fn()

    diff := time.Now().Sub(earlier)

    <-time.After(interval - diff)

}


quit := make(chan bool, 1)


go func() {

    // The total time to run one iteration of the task

    interval := 5 * time.Second


    for {

        select {

        case <-quit:

            return

        default:

            runAndWait(interval, task)

        }

    }

}()


查看完整回答
反對 回復 2023-07-17
  • 1 回答
  • 0 關注
  • 129 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號