python多线程编程: 如何暴力但不失优雅地关闭线程

问题需求

多i线程编程中,常常遇到的1个头痛问题是,主线程退出后,子线程未能正常退出,造成一些数据丢失,文件破坏的隐患,或者成为僵尸进程,占用系统资源。
前面文章介绍了几种优雅关闭线程的方法,但也有一些网友提出疑问:是否可以暴力但不留隐患杀死线程?, 答案是:Yes!

Python其它关闭线程的方法,请参阅本人博文 Python多线程编程:如何优雅地关闭线程

暴力但不失优雅地关闭线程的解决方法

1、解决方法说明

1)所谓暴力就是按 Ctrl+C, 或者 Linux下发送kill -9 强制中止程序信号等。
2)通过python内置signal模块,实时捕捉到Ctrl+C信号,并触发回调函数。
3)为了让代码更健壮,在回调函中抛出了1个自定义异常类,在主线程中捕获到该异常后,通过设置event对象安全地关闭线程。

2、完整代码

下面是完整代码,在win10下测试,支持按 Ctrl+C键, 或者通过任务面板关闭进程,均可安全地关闭线程,杜绝隐患。
Linux系统下,将信号 signal.SIGTERM 改为 signal.SIGKILL即可,可用kill -9 命令直接杀死线程。

from math import e
import time
import threading
import signal
 
 
class Task(threading.Thread):
 
    def __init__(self):
        threading.Thread.__init__(self)
 
        # shutdown_flag 用于关闭线程
        self.shutdown_flag = threading.Event()
 
        # ... Other thread setup code here ...
 
    def run(self):
        print(f'Thread #{self.ident} started')
 
        while not self.shutdown_flag.is_set():
            # 线程代码可以放在这里            
            print(f"Thread #{self.ident} is running...")
            time.sleep(1)
 
        # ... Clean code put here ...
        print(f'Thread #{self.ident} stopped')
 
 
class ServiceExit(Exception):
    """
    自定义1个异常类,用于退出线程
    """
    def __init__(self,message="force to quit"):
        self.message = message
        super(ServiceExit,self).__init__(self.message)
    
    # __str__ is to print() the message
    def __str__(self):
        return(repr(self.message))
 
 
def handler_quit(signum, frame):
    """信号处理函数"""
    print('Caught signal %d' % signum)
    raise ServiceExit("当前线程被强制退出...")
 
 
def main():
 
    # 注册信号回调函数
    signal.signal(signal.SIGTERM, handler_quit)
    signal.signal(signal.SIGINT, handler_quit)
 
    print('Starting main program')
 
    # Start the sub threads
    try:
        t1 = Task()
        t2 = Task()
        t1.start()
        t2.start()
 
        # 保持主线程运行,否则无法收到信号
        while True:
            time.sleep(0.5)
 
    except ServiceExit as e:
        t1.shutdown_flag.set()
        t2.shutdown_flag.set()
        # Wait for the threads to close...
        t1.join()
        t2.join()
        print(e.message)
 
    print('Exiting main program')
 
 
if __name__ == '__main__':
    main()

运行output 如下

Starting main program
Thread #119072 started
Thread #119072 is running...
Thread #119076 started
Thread #119076 is running...
Thread #119076 is running...
Thread #119072 is running...
Thread #119072 is running...
Thread #119076 is running...
Thread #119076 is running...
Thread #119072 is running...
Caught signal 2
Thread #119072 stopped
Thread #119076 stopped
当前线程被强制退出...
Exiting main program
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python线编程是指在Python中使用多个线程同时执行任务的技术。由于Python中的全局解释器锁(Global Interpreter Lock,简称GIL)的限制,Python线程并不能真正地实现多核并行,但是可以通过多线程来提升程序的响应速度和并发处理能力。 Python中的多线编程可以使用threading模块来实现,该模块提供了Thread类来创建和管理线程。下面是一个简单的例子: ```python import threading def worker(): print("I am running in thread", threading.current_thread().name) threads = [] for i in range(5): t = threading.Thread(target=worker) threads.append(t) t.start() for t in threads: t.join() ``` 这段代码创建了5个线程,并让它们同时执行worker函数。在worker函数中,调用了threading.current_thread().name函数来打印当前线程的名称。最后,主线程等待所有子线程执行完毕后再退出。 Python线编程需要注意以下几点: 1. 多线程并不能真正地实现多核并行,因为Python中的全局解释器锁限制了同一时间只能有一个线程执行Python字节码。 2. 多线程共享进程的内存空间,需要注意线程安全问题,例如多个线程同时访问同一个共享变量可能会出现数据竞争的问题。 3. Python中的多线程可以通过锁机制来实现线程间的同步和互斥,避免数据竞争的问题。常用的锁包括互斥锁、读写锁、信号量等。 4. 在使用多线编程时,需要考虑线程的创建和销毁、线程间的通信和同步等问题,需要综合考虑程序的性能和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值