V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rizon
V2EX  ›  程序员

如何停止线程池中的线程

  •  
  •   rizon ·
    othorizon · 2019-10-31 15:08:36 +08:00 · 7042 次点击
    这是一个创建于 1851 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本来以为是个很简单的事,用起来才发现完全不是那么回事。。。

    场景是这样的,我用线程池去运行一个任务,希望在任务超时后就可以停止掉。 可是我发现 get 的超时不会让线程停下来,cancle 也不会让线程停下来。。。

    所以到底该怎么停止线程?释放出线程池?

    第 1 条附言  ·  2019-10-31 18:38:07 +08:00
    那再问一下,线程里面开线程。父线程退出后,子线程还会继续运行吗
    11 条回复    2019-11-01 07:29:27 +08:00
    defphilip
        1
    defphilip  
       2019-10-31 15:16:31 +08:00
    正确的做法,是不要去停止线程,线程正常消亡才是正常的逻辑
    要做取消,可以在外部设置类似于 disable 一样的标志位,线程内函数判断这个标志
    ClericPy
        2
    ClericPy  
       2019-10-31 16:13:07 +08:00
    这个不管什么语言, 在 stackoverflow 上都有人很详细的分析了, 自己去看看吧, 基本是个费力不讨好的操作, 一般都是在线程内自己主动停下.

    目前就我所知, 除非语言本身考虑到处理这种情况, 不烦很复杂的. 比如在用 python 协程的时候, 挺多情况超时捎带的 cancel 可以把没跑完的协程给终止, 不过有些协程粒度不细, 还是停不下来.
    yyyyfan
        3
    yyyyfan  
       2019-10-31 16:26:25 +08:00
    while(continueProcessing){
    ...
    }
    一般是采用标志位去停止,话说一般超时是会有回调的吧
    DsuineGP
        4
    DsuineGP  
       2019-10-31 16:55:17 +08:00
    如果是 java 的话,调用执行线程的中断(interrupt)方法,在执行线程的业务代码中可以响应中断,并处理一些释放资源的逻辑.
    但也并不是所有的线程状态都能响应中断,并发库中有一些更容易使用更安全的类,推荐看一下.
    rizon
        5
    rizon  
    OP
       2019-10-31 18:38:28 +08:00 via iPhone
    @defphilip
    @ClericPy
    那再问一下,线程里面开线程。父线程退出后,子线程还会继续运行吗
    ClericPy
        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), 会发现子线程是没有停止退出的, 这里不等只是让程序进程退出而不等.
    ddup
        7
    ddup  
       2019-10-31 20:39:32 +08:00 via Android
    子线程不会因为父线程的退出而停止,可以参考下 .NET CancellationToken 机制的实践。
    yidinghe
        8
    yidinghe  
       2019-10-31 20:42:45 +08:00 via Android
    线程实际上是没有……等下楼主你用的什么语言?
    qyvlik
        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. 进程被杀,线程一般也会退出,所以杀进程吧。
    zhuangzhuang1988
        10
    zhuangzhuang1988  
       2019-10-31 23:57:47 +08:00
    @ddup 正解,微软的东西一直做得很完善的
    还有进度报告
    simuhunluo
        11
    simuhunluo  
       2019-11-01 07:29:27 +08:00 via Android
    父进程被杀,子进程还在,并且他的父进程 ID 置为 1。可以设置子进程为守护进程,这样父进程杀了之后子进程也没了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1173 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:03 · PVG 02:03 · LAX 10:03 · JFK 13:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.