首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

科普:为什么SpringBoot中main方法执行完毕程序不会直接退出

针对这个问题我们可以转化一下思路:一个JVM进程,在什么情况下会正常退出?...大部分人应该都知道使用System.exit()或Runtime.exit()可以直接导致当前JVM进程退出,但是仔细想想这个好像跟SpringBoot没啥关系哈 另外一个可能会导致进程退出的是所有的非...daemon进程完全终止,那么根据这个条件反推的话是不是说只要保证SpringBoot进程中包含1个以上的daemon进程就可以保证程序不会退出 接下来我们去看下SpringBoot是如何基于这个特性实现的...// ... } 在await方法中,实际上当前线程在一个while循环中每10秒检查一次 stopAwait这个变量,它是一个volatile类型变量,用于确保被另一个线程修改,...这就是该线程不退出的原因,也就是整个spring-boot应用不退出的原因。

4.5K20

国标GB28181安防视频平台EasyGBS大批量通道接入,创建角色接口响应的排查

有用户反馈,在EasyGBS的项目现场,接入了大批量的设备,设备通道高达30万+,当用户在平台创建角色时,会出现长时间响应并且页面崩溃的情况。...这是因为创建角色时,会获取所有设备的通道,接口返回长时间响应,并且该接口返回的数据过大,因此导致前端页面崩溃,影响角色添加等功能的使用。针对该情况,技术人员立即对项目现场进行了排查。...修改原先的mysql查询,添加Group过滤,如下:在获取设备下通道时,通过多表联查,保证数据及时返回和避免数据量过大。...t_role_channel.channel_id WHERE (t_channels.device_id = '44010600082008008001') AND t_role_channel.role_id = 3 ;参考代码:经过优化

17530
您找到你想要的搜索结果了吗?
是的
没有找到

go的channel_go channel原理

:= <-ch // ch中读取一个值并保存到val变量中 val,ok = <-ch // ch读取一个值,判断是否读取成功,如果成功则保存到val变量中 其实很简单,当ch出现在...由于recver中读取channel的操作放在了无限for循环中,表示recver goroutine将一直阻塞,直到channel ch中读取到数据,读取到数据后进入下一轮循环由被阻塞在recv =...当加1发送给channel的数据为10之后,某goroutine将关闭count channel,该goroutine将退出,wg的计数器减1,另一个goroutine因等待recv而阻塞的状态将因为...当select未在循环中时,它将只对所有case评估一次,这次结束就结束select。某次评估过程中如果有满足条件的case,则所有其它case都直接结束评估,并退出此次select。...然后在无限循环中使用select轮询这两个通道是否可读,最后main goroutine在1秒强制中断所有goroutine。

60250

Go两周入门系列-协程(goroutine)

说明:因为say("hello")函数是在主协程中运行的,如果say("hello")函数先执行完成,那么主协程就会退出,程序就结束了,其他执行完成的协程也会强制退出,后面介绍如何通过channel解决这种情况...3.channel channel,可以翻译成通道,是go语言推荐的协程之间的通信机制,channel的通信方式可以形象的想象成一根空心的管道,从一头塞数据进去,另外一头读取数据,协程通过channel...// channel变量c中读取数据,保存到变量v中 v := <-c // channel变量c中读取数据,数据直接丢弃 <-c 提示:如果channel中没有数据,会阻塞协程,直到channel...channel的操作会一直阻塞,直到收到数据为止,这样就可以解决前面例子中,主协程退出,子协程执行完就强制退出的问题。...通道读取10次数据 fmt.Println(<-c) } // 往quit通道中发送数据0,通知fibonacci函数退出计算,主协程就结束了

21520

Go并发编程

channel 会产生 panic 重复关闭同一个 channel 会产生 panic 向一个已关闭的 channel 发送消息会产生 panic 已关闭的 channel 读取消息不会产生 panic...已关闭的 channel 读取消息永远不会阻塞,并且会返回一个为 false 的值,用以判断该 channel 是否已关闭(x,ok := <- ch) 关闭 channel 会产生一个广播机制,所有向...释放锁 // 第 3 个协程获得读锁, sleep 1s ,释放锁 // 第 0 个协程获得读锁, sleep 1s ,释放锁 // 第 1 个协程获得读锁, sleep 1s ,释放锁 // 程序退出...通过通道发送信号,引导协程退出,开发者手动控制协程 ::: details 手动控制协程关闭 func main() { stopChan := make(chan bool) manualControlChan...// 监控器3,接收到通道值为:false,监控结束。 // 主程序退出!!

53300

总结了才知道,原来channel有这么多用法!V2

使用for range读channel 场景 当需要不断channel读取数据时。...原理 使用for-range读取channel,这样既安全又便利,当channel关闭时,for循环会自动退出,无需主动监测channel是否关闭,可以防止读取已经关闭的channel,造成读到数据为通道所存储的数据类型的零值...- false:通道关闭,无数据读到。 关闭的channel读值读到是channel所传递数据类型的零值,这个零值有可能是发送者发送的,也可能是channel关闭了。...使用select处理多个channel 场景 需要对多个通道进行同时处理,但只处理最先发生的channel时 原理 select可以同时监控多个通道的情况,只处理阻塞的case。...close(h.stopCh) // 可以使用WaitGroup等待所有协程退出 } // 收到停止,不再处理请求 func (h *Handler) loop() error {

1.8K30

GO通道和 sync 包的分享

,写法就比较形象,使用 <- 来指向是通道里面读取数据,还是通道中发送数据 向通道发送数据 // 创建一个通道 ch := make(chan int) // 发送数据给通道 ch <- 1 我们看到箭头的方向是...接收数据 发送数据 阻塞 发送数据 发送数据 阻塞 发送数据 关闭 panic 关闭通道成功待数据读取完毕返回零值 关闭通道成功直接返回零值 关闭通道成功待数据读取完毕返回零值 关闭通道成功待数据读取完毕返回零值...,发送方一直在阻塞,通道中一直未有协程读取数据,导致死锁 我们的解决办法就是创建另外一个协程,将数据通道中读出来即可 package main import "fmt" func recvData..., 只写 不能读 // int 单向 通道 , 只读 不能写 // 遍历 读取in 通道,若 in通道 数据读取完毕,则阻塞,若in 通道关闭,则退出循环 for i := range...数据读取完毕,则阻塞,若in 通道关闭,则退出循环 for i := range in { fmt.Println(i) } } func main() { // 创建

1K30

GO 语言的并发模式你了解多少?

,咱们需要关注两类,一种是一次性的任务,咱们 go 出来,执行简单任务完毕直接退出,一种是常驻程序,需要优雅退出,处理一些垃圾回收的事情 例如这样: 主程序中设置一个通道变量 ch ,类型为 os.Signal...并且使用 sync.WaitGroup 来控制 当主协程在 quit 通道中写入数据时,主动通知所有子协程退出 help 中的另外一个协程读取到 quit 通道中的数据,便 close 掉 j 通道,触发所有的子协程读取...j 通道值的时候,得到的 ok 为 false,进而所有子协程退出 wg.Wait() 等待所有子协程退出,再在 quit 中写入数据 主协程此时 quit 中读取到数据,则知道所有子协程全部退出...ch2 的内容,读取到内容,挨个打印出来 管道模式有两种模式,扇出模式 和 扇入模式,这个比较好理解 扇出模式:多种类型的数据同一个通道 channel 中读取数据,直到通道关闭 扇入模式:输入的时候有多个通道...channel,程序将所有的通道内数据汇聚,统一输入到另外一个通道channel A 里面,另外一个程序则从这个通道channel A 中读取数据,直到这个通道A关闭为止 超时模式和取消模式化 超时模式

26420

这些 channel 用法你都用起来了吗?

分别开辟两个子协程,其中子协程 1 在 2 秒之后写入数据给到 c1,另外一个子协程 2 在 1 秒之后写入数据给到 c2 主协程循环等待阻塞读取 c1 , c2 里面的数据,读取将对应的标识 ok1.../ ok2 置为 true 当 ok1 和 ok2 都为 true 的时候,退出循环,结束程序 func main() { c1, c2 := make(chan struct{}), make...nil 的 channel,咱就可以这样来调整一下关于通道使用的情况 修改为,通道读取数据时,先判断通道是否已经关闭,若关闭则将通道设置为 nil,若关闭,则打印我们通道读取的数据(此处模拟直接打印一个固定的值...关闭通道通道变量不应该就变成 nil 了吗?为什么我们还要自己去设置为 nil? 实际上这就是我们对于通道的基础知识不扎实了,关闭通道通道本身并不会变为 nil。...能够写入数据到 worker channel 通道中,则开始干活,干完之后, worker channel 通道中读出数据 func main() { j := make(chan int

20310

golang面试官:for select时,如果通道已经关闭会怎么样?如果select中只有一个case呢?

解释 1.for循环里被关闭的通道 c通道是一个缓冲为0的通道,在main开始时,启动一个协程对c通道写入10,然后就关闭掉这个通道。...在main中通过 x, ok := <-c 接受通道c里的值,输出结果里看出,确实通道里读出了之前塞入通道的10,但是在通道关闭,这个通道一直能读出内容。...2.怎么样才能不读关闭通道 x, ok := <-c 返回的值里第一个x是通道内的值,ok是指通道是否关闭,当通道被关闭,ok则返回false,因此可以根据这个进行操作。...至于为什么读一个初始化的通道会出现阻塞,可以看我的另一篇 对初始化的的chan进行读写,会怎么样?为什么? 。select中如果任意某个通道有值可读时,它就会被执行,其他被忽略。...第一次读取case能读到通道里的10 第二次读取case能读到通道已经关闭的信息。此时将通道置为nil 第三次读取case时main协程会被阻塞,此时整个进程没有其他活动的协程了,进程deadlock

15100

golang面试官:for select时,如果通道已经关闭会怎么样?如果select中只有一个case呢?

main中通过 x, ok := <-c 接受通道c里的值,输出结果里看出,确实通道里读出了之前塞入通道的10,但是在通道关闭,这个通道一直能读出内容。...2.怎么样才能不读关闭通道 x, ok := <-c 返回的值里第一个x是通道内的值,ok是指通道是否关闭,当通道被关闭,ok则返回false,因此可以根据这个进行操作。...至于为什么读一个初始化的通道会出现阻塞,可以看我的另一篇 对初始化的的chan进行读写,会怎么样?为什么? 。select中如果任意某个通道有值可读时,它就会被执行,其他被忽略。...第一次读取case能读到通道里的10 第二次读取case能读到通道已经关闭的信息。...此时将通道置为nil 第三次读取case时main协程会被阻塞,此时整个进程没有其他活动的协程了,进程deadlock 总结 select中如果任意某个通道有值可读时,它就会被执行,其他被忽略。

1.3K10

Go 语言并发编程系列(八)—— 通道类型篇:错误和异常处理

在并发编程的通信过程中,最需要处理的就是超时问题:比如向通道发送数据时发现通道已满,或者通道接收数据时发现通道为空。如果不正确处理这些情况,很可能会导致整个协程阻塞并产生死锁。...select 语句实现 ch 通道读取超时效果 select { case <- ch: fmt.Println("接收到 ch 通道数据")...通道中接收到数据后继续执行,无论对 ch的读取是否还处于等待状态,从而实现 1 秒超时的效果。...执行上述代码,打印结果如下: 超时1秒,程序退出 而如果没有 timeout 通道和上述 select 机制, ch 通道接收数据会得到如下 panic(死锁): fatal error: all goroutines...如果我们试图在通道 ch 关闭发送数据到该通道,则会得到如下 panic: panic: send on closed channel 而如果我们试图在通道 ch 关闭再次关闭它,则会得到如下 panic

75020

Go Channel(收藏以备面试)

看几个实际的例子: package main import "fmt" func main() { var c1 chan int // 可读写的通道 var c2 chan...=%+v \n",c2) fmt.Printf("c3=%+v \n",c3) } 只声明初始化的通道值是nil,需要初始化之后才会分配存储空间,通道初始化使用make方法。...读取通道的数据时,通道左边如果是一个变量,会返回通道中的元素;如果是两个变量,第一个是通道中复制出来的元素,第二个是通道的状态。其中通道的状态为true时,通道关闭,状态为fasle时,通道关闭。...因为main函数也是一个goroutine,它执行完成就会退出,而不会判断是否有其他协程需要执行。我们让main goroutine等待1s钟,给其他协程足够的执行时间。...通道读取数据的流程和写入类似,首先判断是否有等待写入的协程,如果有的话,启动协程的写入操作,复制数据;否则继续判断缓冲区中是否有数据,如果有的话复制数据;否则,把当前goroutine放入等待读取的队列

43211

Go基础系列:channel入门

:= <-ch // ch中读取一个值并保存到val变量中val,ok = <-ch // ch读取一个值,判断是否读取成功,如果成功则保存到val变量中 其实很简单,当ch出现在...由于recver中读取channel的操作放在了无限for循环中,表示recver goroutine将一直阻塞,直到channel ch中读取到数据,读取到数据后进入下一轮循环由被阻塞在recv =...当加1发送给channel的数据为10之后,某goroutine将关闭count channel,该goroutine将退出,wg的计数器减1,另一个goroutine因等待recv而阻塞的状态将因为...channel的关闭而失败,ok状态码将让该goroutine退出,于是wg的计数器减为0,main goroutine因为wg.Wait()而继续执行后面的代码。...然后在无限循环中使用select轮询这两个通道是否可读,最后main goroutine在1秒强制中断所有goroutine。

69940

总结了才知道,原来channel有这么多用法!

,只进行了声明,或者手动赋值为nil active,正常的channel,可读或者可写 closed,已关闭,千万不要误认为关闭channel,channel的值是nil channel可进行3种操作...使用for range读channel 场景:当需要不断channel读取数据时 原理:使用for-range读取channel,这样既安全又便利,当channel关闭时,for循环会自动退出,无需主动监测...channel是否关闭,可以防止读取已经关闭的channel,造成读到数据为通道所存储的数据类型的零值。...使用select处理多个channel 场景:需要对多个通道进行同时处理,但只处理最先发生的channel时 原理:select可以同时监控多个通道的情况,只处理阻塞的case。...    close(h.stopCh) 3 4    // 可以使用WaitGroup等待所有协程退出 5} 6 7// 收到停止,不再处理请求 8func (h *Handler) loop

2.2K20
领券