V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
yuzhibott
V2EX  ›  Python

在异步进程下创建线程,线程执行循环任务,为什么线程还没执行完任务进程就退出了?

  •  
  •   yuzhibott · 2017-09-25 17:33:29 +08:00 · 2454 次点击
    这是一个创建于 2396 天前的主题,其中的信息可能已经有所发展或是发生改变。
    13 条回复    2017-09-27 14:03:54 +08:00
    yuzhibott
        1
    yuzhibott  
    OP
       2017-09-25 17:34:32 +08:00
    num = 0

    def test1(*data):
    global num
    i = data[0]
    while True:
    if num == 10:
    num = 0
    break
    print(i)
    num += 1
    time.sleep(2)

    def test2(*data):
    i = data[0]
    threading.Thread(target=test1, args=(i,)).start()
    print("done")

    pool = multiprocessing.Pool(processes=5)
    for j in range(2):
    pool.apply_async(test2, (j,))
    yuzhibott
        2
    yuzhibott  
    OP
       2017-09-25 17:35:50 +08:00
    大概代码如上,不能用 join(),因为实际中是多任务定时处理,每个任务时间不一样
    yuzhibott
        3
    yuzhibott  
    OP
       2017-09-25 17:50:27 +08:00
    num = 0

    def test1(*data):
    global num
    i = data[0]
    while True:
    if num == 10:
    num = 0
    break
    print(i)
    num += 1
    time.sleep(2)

    def test2(*data):
    i = data[0]
    threading.Thread(target=test1, args=(i,)).start()
    print("done")

    pool = multiprocessing.Pool(processes=5)
    for j in range(2):
    pool.apply_async(test2, (j,))
    shibingsw
        4
    shibingsw  
       2017-09-25 17:57:14 +08:00
    join 和时间长短有什么关系。。
    yuzhibott
        5
    yuzhibott  
    OP
       2017-09-25 17:59:57 +08:00
    @shibingsw 多个定时任务啊,每个定时不一样,join 不是只能一个一个线程执行么
    clino
        6
    clino  
       2017-09-25 18:00:30 +08:00
    "不能用 join(),因为实际中是多任务定时处理,每个任务时间不一样"
    join 做了等待的时候,你如果不用,那么就要自己来实现这个等待的部分,否则不等待就是直接退出了嘛
    scriptB0y
        7
    scriptB0y  
       2017-09-25 18:02:27 +08:00
    同意 #6

    join 阻塞主线程,如果不想用 join 的话,必须让主线程的运行时间最长,否则主线程跑完进程结束
    shibingsw
        8
    shibingsw  
       2017-09-25 19:33:37 +08:00
    @yuzhibott 你把所有线程都启动了,然后再一个一个的 join 不就行了?要是还不理解你应该去看看书了~
    ryd994
        9
    ryd994  
       2017-09-26 05:07:54 +08:00
    不能用 join,就不能检查 is_alive 了?
    再说了,谁说不能 join ?一个一个 join 过去就行,全 join 完退出
    justou
        10
    justou  
       2017-09-26 08:51:32 +08:00
    如果不是创建的后台线程, 不在主线程 join 的话, 主线程结束, 子线程就强制退出了;
    如果是后台线程, 主线程结束后, 子线程自个跑自个的:

    from threading import Thread
    from time import sleep

    def work():
    sleep(5)
    with open("test.txt", 'w') as fout:
    pass

    if __name__ == "__main__":
    t = Thread(target=work)
    t.setDaemon(True)
    t.start()
    petelin
        11
    petelin  
       2017-09-27 13:25:01 +08:00
    @justou 后台线程作用是, 当主线程退出的时候, 不用管他们(那他们能欢快的在后台运行吗? 看进程, 进程都退出了,直接被干掉). 反而非后台进程, 主进程即使不 join, 退出之前也要等子线程结束.

    所以还是要学习一个.
    petelin
        12
    petelin  
       2017-09-27 13:36:56 +08:00
    那么这段代码问题是, 主进程跑完之后, 所有子进程都被干掉了.无论你子进程在干什么, 直接被干掉.

    所有需要在主进程加一段代码
    pool.close()
    pool.join()

    这样看起来就完了, 主进程会等待子进程完成, 而子进程会等待线程完成

    可是子进程不会等待线程完成, 所以
    t.start()
    t.join()

    那么为什么子进程不会等待非守护线程结束呢??? 我去学习一个
    petelin
        13
    petelin  
       2017-09-27 14:03:54 +08:00
    @petelin 说的有点问题, 并不是主线程等待子线程都完成在退出(那是 join 干的事), 而是 python 解释器保证 当没有活跃的进程之后才退出(所以主线程先退出, 子线程继续执行, 知道完成 python 进程退出是有可能的).
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5265 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 07:48 · PVG 15:48 · LAX 00:48 · JFK 03:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.