threading 模块提供了多线程,并且在创建的线程中为我们提供了几个使用的方法,ioin 和 setDaemon ,这两个方法使我们可以控制在子线程执行的时候,是否根据主线程的状态去收回子线程,栏下面代码:
import threading from time import sleep , ctime def music(): sleep(5) print('我在听音乐%s'%ctime()) def movie(): sleep(10) print('我在听音乐%s'%ctime()) threads = [] t1 = threading.Thead(target=music, args=()) threads.append(t1) t2 = threading.Thead(target=movie, args = ()) threads.append(t2) for item in threads: item.start() item.join(); #join([setouttime]) print('主进程执行完毕%s'%ctime());
上面的代码由于使用了setDaemon 所以在最终的结果只会打印出 ‘主进程执行完毕‘ ,因为设置的 setDaemon 会对主线程进行守护, 也就是主线程结束,所有子线程会被收回,子线程不论执行到哪,都会被中断。
import threading from time import sleep , ctime def music(): sleep(5) print('我在听音乐%s'%ctime()) def movie(): sleep(10) print('我在听音乐%s'%ctime()) threads = [] t1 = threading.Thead(target=music, args=()) threads.append(t1) t2 = threading.Thead(target=movie, args = ()) threads.append(t2) for item in threads: item.start()
item.join() # join([setouttime]) print('主进程执行完毕%s'%ctime());
这里可以看到在 for 循环的外面添加了 join(),这里主线程就会阻塞在这,会等到 item(也就是t2)执行完毕以后才会往下执行,如果 t1 此时还没有执行完也不会被收回,此时主线程会执行完毕,服务被挂起,直到 t1 执行完毕。
注:这里为什么会是 t2 ,因为 for 循环执行完毕后 item 保存的就是 t2 (也就是最后一个列表元素);
以上的两个东西你可以同时使用,如果你是同时使用,以上例中 t2 如果执行完毕,此时 t1 若没有执行完毕就会被收回,主线程结束。
如果你两个都不使用,主线程不会阻塞等待子线程,他会挂起,等待子线程进行完毕结束服务。
下面来一个总结:
单独使用 setDaemon(True)时,子线程会在主线程结束时被收回,也就是线程中断。
单独使用 join([ settimeout ])时,主线程会阻塞等待添加 join 的子线程进行完毕,直到主线程执行完毕,执行完毕后服务会挂起,等待其他的其他的子进程结束后关闭。
两者同时使用,主线程会阻塞在添加 join 的子线程处,直到这个子线程执行完毕继续执行主线程,当主线程执行完毕时,还没有指向完毕的子进程会被回收终止。
两者都不用时,主线程不会阻塞等待,而是执行完毕后挂起,等待所有子进程执行完毕后关闭。