这个才是正确嘛,线程名确实是可以通过 Ps 看出来的嘛!
不过为啥 Python 那个看不到呢?既然是通过setName设置线程名的,那就看看定义咯:
看到这里其实只是在Thread对象的属性设置了而已,并没有动到根本,那肯定就是看不到咯~
这样看起来,我们已经没办法通过ps或者/proc/这类手段在外部搜索 python 线程名了,所以我们只能在 Python 内部来解决。
于是问题就变成了,怎样在 Python 内部拿到所有正在运行的线程呢?
threading.enumerate可以完美解决这个问题!Why?
Because 在下面这个函数的 doc 里面说得很清楚了,返回所有活跃的线程对象,不包括终止和未启动的。
因为拿到的是 Thread 的对象,所以我们通过这个能到该线程相关的信息!
请看完整代码示例:
输出:
代码看起来有点长,但是逻辑相当简单,Thread-test1和Thread-test2都是打印出当前的 pid、线程 id 和 线程名字,然后 3s 后退出,这个是想模拟线程正常退出。
而Checker线程则是每秒通过threading.enumerate输出当前进程内所有活跃的线程。
可以明显看到一开始是可以看到Thread-test1和Thread-test2的信息,当它俩退出之后就只剩下MainThread和Checker自身而已了。
销毁指定线程
既然能拿到名字和线程 id,那我们也就能干掉指定的线程了!
假设现在Thread-test2已经黑化,发疯了,我们需要制止它,那我们就可以通过这种方式解决了:
在上面的代码基础上,增加和补上下列代码:
输出
一顿操作下来,虽然我们这样对待Thread-test2,但它还是关心着我们:多喝热水,
PS: 热水虽好,八杯足矣,请勿贪杯哦。
书回正传,上述的方法是极为粗暴的,为什么这么说呢?
因为它的原理是:利用 Python 内置的 API,触发指定线程的异常,让其可以自动退出;
万不得已真不要用这种方法,有一定概率触发不可描述的问题。切记!别问我为什么会知道…
为什么停止线程这么难
多线程本身设计就是在进程下的协作并发,是调度的最小单元,线程间分食着进程的资源,所以会有许多锁机制和状态控制。
如果使用强制手段干掉线程,那么很大几率出现意想不到的bug。 而且最重要的锁资源释放可能也会出现意想不到问题。
我们甚至也无法通过信号杀死进程那样直接杀线程,因为 kill 只有对付进程才能达到我们的预期,而对付线程明显不可以,不管杀哪个线程,整个进程都会退出!
而因为有 GIL,使得很多童鞋都觉得 Python 的线程是Python 自行实现出来的,并非实际存在,Python 应该可以直接销毁吧?
然而事实上 Python 的线程都是货真价实的线程!
什么意思呢?Python 的线程是操作系统通过 pthread 创建的原生线程。Python 只是通过 GIL 来约束这些线程,来决定什么时候开始调度,比方说运行了多少个指令就交出 GIL,至于谁夺得花魁,得听操作系统的。
如果是单纯的线程,其实系统是有办法终止的,比如:pthread_exit,pthread_kill或pthread_cancel
很可惜的是: Python 层面并没有这些方法的封装!我的天,好气!可能人家觉得,线程就该温柔对待吧。
如何温柔退出线程
想要温柔退出线程,其实差不多就是一句废话了~
现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。
分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!