目标:多线程运行过程中ctrl+c即可中断整个程序运行。
demo1: 多线程为普通线程时==》ctrl+c无法退出程序
def foo():
print(123)
time.sleep(1)
print("end123")
def bar(para):
print("start thread:{}".format(para))
time.sleep(20)
print("end thread:{}".format(para))
if __name__ == '__main__':
ths = []
for i in range(10):
t=Thread(target=bar,args=(i,))
# t.daemon = True
ths.append(t)
for item in ths:
item.start()
print('main end')
》》
demo2: 设置为守护线程加join阻塞主程序 ==》 ctrl+c无法退出程序
def foo():
print(123)
time.sleep(1)
print("end123")
def bar(para):
print("start thread:{}".format(para))
time.sleep(20)
print("end thread:{}".format(para))
if __name__ == '__main__':
ths = []
for i in range(10):
t=Thread(target=bar,args=(i,))
t.daemon = True
ths.append(t)
for item in ths:
item.start()
for item in ths:
print('join-')
item.join()
print('main end')
demo3:引入信号处理,查看信号接收情况
def foo():
print(123)
time.sleep(1)
print("end123")
def bar(para):
print("start thread:{}".format(para))
time.sleep(20)
print("end thread:{}".format(para))
def handler(signum, frame):
global is_exit
is_exit = True
print("receive a signal {0}, is_exit = {1}".format(signum, is_exit))
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
ths = []
for i in range(10):
t=Thread(target=bar,args=(i,))
# t.daemon = True
ths.append(t)
for item in ths:
item.start()
print('main end')
信号接收情况:
1.非daemon线程执行时,主线程代码执行完后,要等线程执行完才处理接收的信号 --信号不能被立即处理
2.join阻塞时信号会被接收,不会被处理,join完成后会处理信号 -- 信号不能被立即处理
综上:主线程代码未执行完毕且非阻塞的情况下才能立即处理信号
改进:
1.使用thread.isAlive()判断各个子线程是否执行完毕;在主线程中不使用join方法以免不能立即处理信号
2.使用全局变量标志是否应该退出主线程,需要在信号处理程序中根据接收的信号改变全局变量的值
3.配置所有线程为daemon:主线程退出则整个进程退出
demo4:开启多线程,ctrl+c即退出程序
def foo():
print(123)
time.sleep(1)
print("end123")
def bar(para):
print("start thread:{}".format(para))
time.sleep(10)
print("end thread:{}".format(para))
def handler(signum, frame):
global is_exit
is_exit = True
print("receive a signal {0}, is_exit = {1}".format(signum, is_exit))
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
ths = []
global is_exit
is_exit = False
for i in range(10):
t=Thread(target=bar,args=(i,))
t.daemon = True
ths.append(t)
for item in ths:
item.start()
while 1:
print('======', is_exit)
alive = False
for item in ths:
alive = alive or item.isAlive()
if not alive or is_exit:
break
time.sleep(1)
print('main end')