本来以为是个很简单的事,用起来才发现完全不是那么回事。。。
场景是这样的,我用线程池去运行一个任务,希望在任务超时后就可以停止掉。 可是我发现 get 的超时不会让线程停下来,cancle 也不会让线程停下来。。。
所以到底该怎么停止线程?释放出线程池?
1
defphilip 2019-10-31 15:16:31 +08:00
正确的做法,是不要去停止线程,线程正常消亡才是正常的逻辑
要做取消,可以在外部设置类似于 disable 一样的标志位,线程内函数判断这个标志 |
2
ClericPy 2019-10-31 16:13:07 +08:00
这个不管什么语言, 在 stackoverflow 上都有人很详细的分析了, 自己去看看吧, 基本是个费力不讨好的操作, 一般都是在线程内自己主动停下.
目前就我所知, 除非语言本身考虑到处理这种情况, 不烦很复杂的. 比如在用 python 协程的时候, 挺多情况超时捎带的 cancel 可以把没跑完的协程给终止, 不过有些协程粒度不细, 还是停不下来. |
3
yyyyfan 2019-10-31 16:26:25 +08:00
while(continueProcessing){
... } 一般是采用标志位去停止,话说一般超时是会有回调的吧 |
4
DsuineGP 2019-10-31 16:55:17 +08:00
如果是 java 的话,调用执行线程的中断(interrupt)方法,在执行线程的业务代码中可以响应中断,并处理一些释放资源的逻辑.
但也并不是所有的线程状态都能响应中断,并发库中有一些更容易使用更安全的类,推荐看一下. |
5
rizon OP |
6
ClericPy 2019-10-31 18:48:21 +08:00
对 py 来说, 取决于子线程是不是 daemon, talk is cheap
from threading import Thread import time def parent(): t = Thread(target=child) t.daemon = True t.start() for i in range(5): print('parent', i) time.sleep(0.5) def child(): for i in range(10): print('child', i) time.sleep(0.5) t = Thread(target=parent) t.run() 执行会发现父线程在子线程 daemon 是 True 的时候不等, False 或默认的时候等. (这是为了定义清晰, 实际主线程看做父线程也一个意思) 但是注意, 这里的不等是不阻塞的意思, 结尾如果加一个 time.sleep(5), 会发现子线程是没有停止退出的, 这里不等只是让程序进程退出而不等. |
7
ddup 2019-10-31 20:39:32 +08:00 via Android
子线程不会因为父线程的退出而停止,可以参考下 .NET CancellationToken 机制的实践。
|
8
yidinghe 2019-10-31 20:42:45 +08:00 via Android
线程实际上是没有……等下楼主你用的什么语言?
|
9
qyvlik 2019-10-31 21:36:54 +08:00
所有语言的线程实现都是类似的,包装了一次系统的线程。如果想停止正在运行中的线程,有几种方式:
1. 代码中检查线程的状态,例如 Java 的 Thread.currentThread().isInterrupted() 2. 语言本身支持 cpu 直接中断线程,然后把线程干掉,不过会有资源泄露的问题,毕竟不是正常退出。 3. 脚本语言的实现支持线程中断,例如你可以自己实现一个脚本引擎,在做指令派发的时候,将 指令 与 线程状态做位运算,线程状态是 0 的话,得到的指令是 0,0 可以定义为中止执行,就达到线程中断的要求。可以看看具体的代码: https://github.com/qyvlik/tinyvm/blob/40bfefac61d9e0409572b5b0c97f700f6f1532c8/tinyvm.cpp#L83 4. 进程被杀,线程一般也会退出,所以杀进程吧。 |
10
zhuangzhuang1988 2019-10-31 23:57:47 +08:00
@ddup 正解,微软的东西一直做得很完善的
还有进度报告 |
11
simuhunluo 2019-11-01 07:29:27 +08:00 via Android
父进程被杀,子进程还在,并且他的父进程 ID 置为 1。可以设置子进程为守护进程,这样父进程杀了之后子进程也没了。
|