python线程基础
一 基本概念
1 并行和并发1 并行,parallel
2 并发,concurrency
2 并发的解决1 队列,缓冲区
2 争抢
3 预处理
4 并行
5 提速
6 消息中间件
3 进程和线程概念1 进程和线程
2 进程和线程的关系
3 进程,线程的理解
4 python中的进程和线程
4 线程的状态1 概述
2 线程状态转换
二 python线程开发1 Thread类
def __init__(self,group=None,target=None,name=None,args=(),kwargs=None,*,daemon=None):
2 实例1 基本创建
#!/usr/bin/poython3.6 #conding:utf-8 import threading def test(): for i in range(5): print (i) print (‘Thread over‘) # 实例化一个线程 t=threading.Thread(target=test) t.start() # 启动一个线程
#!/usr/bin/poython3.6 #conding:utf-8 import threading def test(): for i in range(5): print (i) print (‘Thread over‘) # 实例化一个线程 t=threading.Thread(target=test,name=‘test1‘) t.start() # 启动一个线程 t=threading.Thread(target=test,name=‘test2‘) t.start() # 启动一个线程 # 上述两个线程是并行处理,如果是一个CPU,则是假的平衡
2 线程退出
#!/usr/bin/poython3.6 #conding:utf-8 import threading def test(): count=0 while True: count+=1 if count==3: raise Exception(‘NUMBER‘) print (count) # 实例化一个线程 t=threading.Thread(target=test,name=‘test1‘) t.start() # 启动一个线程
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time def test(): count=0 while True: count+=1 if count==3: raise Exception(‘NUMBER‘) print (count) def test1(): for i in range(5): time.sleep(0.1) print (‘test1‘,i) # 实例化一个线程 t=threading.Thread(target=test,name=‘test‘) t.start() # 启动一个线程 t=threading.Thread(target=test1,name=‘test1‘) #此处启用一个线程,看上述线程能否影响该线程的运行情况 t.start() 结果如下
3 线程传参#!/usr/bin/poython3.6 #conding:utf-8 import threading import time def test(count): while True: count+=1 if count==5: raise Exception(‘NUMBER‘) print (count) # 实例化一个线程 t=threading.Thread(target=test,name=‘test‘,args=(0,)) #此处必须是元祖类型,否则会报错 t.start() # 启动一个线程 4 线程相关属性
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time def test(count): while True: print ("当前线程对象为{}当前处于活动的线程个数为{}".format(threading.current_thread(),threading.active_count())) count+=1 if count==5: break print (count) print(‘当前活着的线程列表为:‘,threading.enumerate()) # 实例化一个线程 t=threading.Thread(target=test,)) #此处必须是元祖类型,否则会报错 t.start() # 启动一个线程 print (‘当前活着的线程列表为:‘,threading.enumerate()) print (‘当前处于活动的线程个数为{},当前主线程为{},当前线程ID为{}‘.format(threading.active_count(),threading.main_thread(),threading.get_ident()))
5 线程实例的属性和方法(getname和setname)
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time def test(count): while True: count+=1 if count==5: break print (count) print (‘当前线程name 为{},ID 为{}‘.format(threading.current_thread().name,threading.current_thread().ident)) # 实例化一个线程 t=threading.Thread(target=test,)) #此处必须是元祖类型,否则会报错 t.start() # 启动一个线程 print (‘主线程状态‘,threading.main_thread().is_alive()) print (‘线程状态‘,threading.current_thread().is_alive())
3 start 和run 的区别与联系1 基本概述
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,self) super().start() def run(self) -> None: print (‘run‘,self) super().run() def work(): print (‘本线程ID为{},主线程ID为{}‘.format(threading.current_thread().ident,threading.main_thread().ident)) print (‘test‘) t=MyThread(target=work,name=‘w‘) t.start()
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,name=‘w‘) t.run()
2 run 和 start 调用次数问题#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,self) super().run() def work(): print (‘test‘) t=MyThread(target=work,name=‘w‘) t.start() time.sleep(3) t.start() #再次启用线程
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,name=‘w‘) t.run() time.sleep(3) t.run()
3 start和run 合用#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,name=‘w‘) t.run() time.sleep(3) t.start()
上述结果表明,run和start的调用不能出现在同一个线程中 4 解决同一代码中调用问题
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,name=‘w‘) t.start() t=MyThread(target=work,name=‘w1‘) t.start()
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,name=‘w‘) t.run() t=MyThread(target=work,name=‘w1‘) t.run() 结果如下 5 run 和start 的作用
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,self) # super().run() def work(): print (‘test‘) t=MyThread(target=work,name=‘w1‘) t.start()
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class MyThread(threading.Thread): # 自定义一个类,其继承Thread的相关start和run属性 def start(self) -> None: print (‘start‘,self) #super().start() def run(self) -> None: print (‘run‘,name=‘w1‘) t.start()
4 多线程概述
5 线程安全
解决方式:
#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 logging.basicConfig(level=logging.INFO) #定义基本级别,默认是WARNING,此处修改为INFO def woker(): for x in range(10): msg="{} is running".format(threading.current_thread()) logging.info(msg) # 日志打印 for x in range(5): t = threading.Thread(target=woker,name="work-{}".format(x)).start()
6 daemon 线程和 non-daemon线程1 概述
#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 logging.basicConfig(level=logging.INFO) #定义基本级别,默认是WARNING,此处修改为INFO def woker(): for x in range(10): msg="{} is running".format(threading.current_thread()) logging.info(msg) # 日志打印 threading.Thread(target=woker,name="work-{}".format(0)).start() print (‘ending‘) print (threading.enumerate()) #主线程因为其他线程的执行,因此其处于等待状态
2 daemon线程#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 logging.basicConfig(level=logging.INFO) #定义基本级别,默认是WARNING,此处修改为INFO def woker(): for x in range(10): msg="{} is running".format(threading.current_thread()) logging.info(msg) # 日志打印 threading.Thread(target=woker,name="work-{}".format(0),daemon=True).start() #主线程一般会在一定时间内扫描属性列表,若其中有non-daemon类型 # 的线程,则会等待其执行完成再退出,若是遇见都是daemon类型线程,则直接退出, print (‘ending‘) print (threading.enumerate()) #主线程因为其他线程的执行,因此其处于等待状态
3 non-daemon 和 damon#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 import time logging.basicConfig(level=logging.INFO) #定义基本级别,默认是WARNING,此处修改为INFO def woker(): for x in range(10): msg="{} {} is running".format(x,threading.current_thread()) logging.info(msg) # 日志打印 time.sleep(0.5) #此处配置延迟,检验是否在non-daemon线程执行完成后及会直接关闭的情况 threading.Thread(target=woker,daemon=True).start() #主线程一般会在一定时间内扫描属性列表,若其中有non-daemon类型 # 的线程,则会等待其执行完成再退出,若是遇见都是daemon类型线程,则直接退出,、 def woker1(): for x in [‘a‘,‘b‘,‘c‘,‘d‘]: msg="{} {} is running".format(x,threading.current_thread()) logging.info(msg) # 日志打印 threading.Thread(target=woker1,name="work-{}".format(0)).start() #主线程一般会在一定时间内扫描属性列表,若其中有non-daemon类型,则不会终止, # 此处默认从父线程中获取属性,父线程中是non-daemon,因此此属性会一直运行,上面的会关闭,但不会影响这个 print (‘ending‘) print (threading.enumerate()) #主线程因为其他线程的执行,因此其处于等待状态 结果如下
#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 import time def woker1(): for x in [‘a‘,threading.current_thread()) logging.info(msg) # 日志打印 logging.basicConfig(level=logging.INFO) #定义基本级别,默认是WARNING,此处修改为INFO def woker(): for x in range(10): msg="{} {} is running".format(x,threading.current_thread()) logging.info(msg) # 日志打印 time.sleep(1) # 此处配置1秒延时,使得主线程看不到孙子线程的non-daemon就关闭 T3=threading.Thread(target=woker1,name="woker{}".format(10),daemon=False) #此处启动的线程默认是non-daemon线程,但由于其父线程是daemon # 及就是下面的T1线程,当T2线程执行完毕后线程扫描,发现没non-daemon线程,则直接退出,此时将不会继续执行T1 的子线程T3,虽然T3是non-daemon。因为其未启动 T3.start() T1=threading.Thread(target=woker,daemon=True)#主线程一般会在一定时间内扫描属性列表,若其中有non-daemon类型 T1.start() # 的线程,则会等待其执行完成再退出,若是遇见都是daemon类型线程,则直接退出,、 T2=threading.Thread(target=woker1,name="work-{}".format(0)) #主线程一般会在一定时间内扫描属性列表,若其中有non-daemon类型,则不会终止, # 此处默认从父线程中获取属性,父线程中是non-daemon,因此此属性会一直运行,上面的会关闭,但不会影响这个 T2.start() print (‘ending‘) print (threading.enumerate()) #主线程因为其他线程的执行,因此其处于等待状态
#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 import time def woker1(): for x in [‘a‘,threading.current_thread()) logging.info(msg) # 日志打印 # time.sleep(1) # 此处配置1秒延时,使得主线程看不到孙子线程的non-daemon就关闭 T3=threading.Thread(target=woker1,daemon=True)#主线程一般会在一定时间内扫描属性列表,若其中有non-daemon类型 T1.start() # 的线程,则会等待其执行完成再退出,若是遇见都是daemon类型线程,则直接退出,、
7 join
#!/usr/bin/poython3.6 #conding:utf-8 import threading import logging # 导入日志打印模块 import time def foo(n): for i in range(n): print (i) time.sleep(0.5) t1=threading.Thread(target=foo,args=(10,),daemon=True) t1.start() # 默认情况下,此线程只能执行少量此,一般不能全部执行 t1.join() # 通过join方法将原本不能执行完成的线程执行完成了
8 threading.local 类
1 局部变量#!/usr/bin/poython3.6 #conding:utf-8 import threading import time def worker(): x=0 # 此处是局部变量 for i in range(10): time.sleep(0.0001) x+=1 print (threading.current_thread(),x) for i in range(10): threading.Thread(target=worker).start()
2 全局变量#!/usr/bin/poython3.6 #conding:utf-8 import threading import time x = 0 # 此处是一个全局变量 def worker(): for i in range(10): global x time.sleep(0.0001) x+=1 print (threading.current_thread(),x) for i in range(10): threading.Thread(target=worker).start()
3 使用类处理#!/usr/bin/poython3.6 #conding:utf-8 import threading import time class A: def __init__(self,x): self.x=x a=A(0) def worker(): for i in range(100): a.x=0 time.sleep(0.0001) a.x+=1 print (threading.current_thread(),a.x) for i in range(10): threading.Thread(target=worker).start()
4 threading.local#!/usr/bin/poython3.6 #conding:utf-8 import threading import time a=threading.local() # 做到隔离,通过TID进行数据的隔离处理不同线程的不同数值问题 def worker(): a.x = 0 for i in range(100): time.sleep(0.0001) a.x+=1 print (threading.current_thread(),a.x) for i in range(10): threading.Thread(target=worker).start()
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time a=threading.local() # 做到隔离,通过TID进行数据的隔离处理不同线程的不同数值问题 def worker(): a.x = 0 for i in range(100): time.sleep(0.0001) a.x+=1 print (threading.current_thread(),a.x) print (threading.get_ident(),a.__dict__) #此处打印线程TID和字典 for i in range(10): threading.Thread(target=worker).start()
5 源代码
6 实践#!/usr/bin/poython3.6 #conding:utf-8 import threading import time X=‘abc‘ ctx=threading.local() ctx.x=123 def work(): print (X) print (ctx) print (ctx.x) #此时的字典中ctx此ctx.x属性,因此其不能打印,其是在线程内部,每个dict对应的值都是独立的 print (‘end‘) threading.Thread(target=work).run() # 此处是本地线程调用,则不会影响 threading.Thread(target=work).start()
#!/usr/bin/poython3.6 #conding:utf-8 import threading import time X=‘abc‘ ctx=threading.local() ctx.x=123 def work(): print (X) print (ctx) ctx.x=100 #内部线程中定义一个局部变量,则可以执行和被调用 print (ctx.x) #此时的ctx 无此属性,因此其不能打印,其是在线程内部, print (‘end‘) threading.Thread(target=work).run() # 此处是本地线程调用,则不会影响 threading.Thread(target=work).start()
7 结论
8 延迟执行Timter1 源码
2 基本实例#!/usr/bin/poython3.6 #conding:utf-8 import threading import datetime start_time=datetime.datetime.now() def add(x,y): print (x+y) print("函数执行时间为{}".format((datetime.datetime.now() - start_time).total_seconds())) t=threading.Timer(3,add,args=(3,4)) t.start() #此处会延迟3秒执行
3 t.cancel() 线程的删除#!/usr/bin/poython3.6 #conding:utf-8 import threading import datetime import time def add(x,y): print (x+y) t=threading.Timer(6,4)) # 此处表示6秒后出结果 t.start() time.sleep(5) t.cancel() #线程被删除
#!/usr/bin/poython3.6 #conding:utf-8 import threading import datetime import time def add(x,y): time.sleep(5) print (x+y) t=threading.Timer(6,4)) # 此处表示6秒后出结果 t.start() time.sleep(10) t.cancel() 结果如下
4 总结
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |