分两个阶段关闭 goroutine,第一阶段先结束 goroutine 的程序逻辑,第二阶段再结束 goroutine 本身
此模式的核心目标如以下三点:
以 golang 来说我们关闭 goroutine 会采取关闭 channel 的方法:
package main
func main() {
done := make(chan bool)
go func() {
for {
select {
case <-done:
// 关闭的善後程序
return
// 其他 case
}
}
}()
close(done)
}
这样的关闭方式其实就有满足以上三点了。收到done channel
被关闭的讯号後,goroutine 会执行case <-done:
区域的善後程序并 return 关闭 goroutine:
所以在平常使用 golang 的时候并不会思考这些问题,Two-phase Termination Pattern 主要是在 java 这类「直接控制 thread 生命周期」的语言才会应用到。
java 的 thread 是用物件封装的,开发者可以控制 thread 的生命周期,并且提供了 Thread.stop()
来关闭 thread,但这是不安全的,他会使运行的 thread 突然中止,就好像正在计算的电脑,插座直接被拔掉了一样。
因此 java 开发者不建议用Thread.stop()
关闭 thread,而是用Thread.interrupt()
加上flag
的方式,
Thread.interrupt()
是为了关闭正处於Thread.sleep()
、Thread.wait()
这类「暂停状态」的 threadflag
是为了关闭正在运行的 thread如下:
try {
while (isRunnable) {
doSomething();
}
} catch (InterruptedException e) {
} finally {
doShutdown();
}
如果 thread 正在运行,while (isRunnable)
这个flag
是false
的话就可以控制是否运行。
如果 thread 运行Thread.sleep()
、Thread.wait()
导致 thread 暂停,Thread.interrupt()
就可以使 thread 抛出异常InterruptedException
,并执行最後的doShutdown()
善後程序。
java 设计会以一个 function 执行Thread.interrupt()
与改变flag
,而正在运行的 thread 再执行关闭动作,
public void terminate() {
isRunnable = false;
interrupt();
}
从Thread.stop()
到Thread.interrupt()
,会较能比对出 Two-phase Termination Pattern 「两阶段终止」的行为。
而 golang 不能直接控制 goroutine 的生命周期,无法做出 java 直接关闭 thread 的行为,所以原本 channel 的做法,即符合 Two-phase Termination Pattern 的目标。
设计一个提示,提示关闭程序後显示。
相关的 code 在Github - go-design-patterns。
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
for {
select {
case <-done:
fmt.Println("bye bye")
os.Exit(1)
}
}
}()
// do something
select {}
}
done{}
channel 会透过signal.Notify()
与os.Interrupt
、syscall.SIGINT
、syscall.SIGTERM
这些关闭相关的 system 讯号绑定,并以 goroutine 的方式一直运作在整个程序。
再执行do something
的部分时,只要我们使用control+c
或者其他关闭程序的方法,channel 接收到关闭讯号就会安全地执行case <-done:
范围的 code,即在 terminal 显示bye bye
提示并关闭程序。
<<: [第九天]从0开始的UnityAR手机游戏开发-介绍Unity写程序的基本语法。
前言 今天我会说明一些开始实作所需要的工具,包含 flask 套件。但单单一个 flask 并不足以...
=x= 🌵 专案优化方向说明。 网站後台优化 : 1. Sign In Page : 验证密码时间较...
box-sizing这个语法可以让设计师或是写程序的人不用去加加减减的计算区块 (比如说线条宽度或是...
在昨天我们讲过Azure小白如何使用Azure Cache for Redis来存取常用资料後 今天...
今天我们就要着手开始实作拉!而造顺序来的话我们最上方都会有个logo跟导览列,接下来就让我们把学过的...