线程(threading)运行在进程内部,可以访问进程中所有内容,multiprocessing 和 threading 的区别之一就是 threading 没有 terminate() 函数。很难终 止一个正在运行的线程,因为这可能会引起代码和时空连续性上的各种问题。要使用线程,程序中所用代码以及程序使用的外部库中的代码,必须是线程安全。没有全局变量是线程非常有用并且安全,线程不会应为数据打架,应为每个线程都是完全独立的。
但线程有时需要修改全局变量,要实现数据共享,这时可以通过让线程在修改变量前加软件锁,这样在进行修改时其他线程会等待。Python多线程用于I/O操作密集型的任务。
线程模块
python中常用的模块为threading。
该模块下常见函数:
active_count()//返回当前存活的线程类对象,线程个数=主线程+子线程
current_thread()//返回当前调用者的控制线程的对象。
get_ident()//返回当前线程的‘线程标识符’。
线程对象:
一个线程可以被标记为“守护线程”,即表示守护线程终结,整个程序才会退出,通过daemon属性来标识。
start():开始线程,一个线程最多只能被调用一次。被安排在对象run()方法一个独立的控制进程中。
run():表示线程开始活动。
join():等待,直到线程结束,这会阻塞调用这个方法的线程,直到join()的线程终结,一个线程可以被多次调用该对象。
name:只用于标识的字符串。
ident:这个线程的‘线程标识符’,若线程未开始则为None。
is_value():返回线程是否存活。
daemon:表示这个线程是否为守护线程,在调用start()前设置好。初始值继承于创建线程;主线程不是守护线程,默认都为daemon=False。
多线程的创建可以分为函数式和类模式创建
函数式:
1 import threading 2 import time,random 3 4 def do_This(strName): 5 for n in range(1,4): 6 print("{0} {1}".format(threading.current_thread().getName(),strName))#返回当前调用者控制线程名 7 time.sleep(3) 8 #当前调用者的控制线程对象和当前存活线程数 9 print("{0} {1}".format(threading.current_thread(),threading.active_count())) 10 11 12 if __name__=='__main__': 13 #线程创建方式,target表示调用函数,args表示当前调用函数传递的参数,name可以为默认值,即可以不用指定,系统自动赋值 14 th1=threading.Thread(target=do_This,args=("Hello!",),name="threading1") 15 th2=threading.Thread(target=do_This,args=("World!",)) 16 17 th1.start()#开启线程 18 th2.start() 19 20 th1.join()#等待线程终止 21 th2.join() 22 print('{0}线程结束'.format(threading.current_thread().getName()))
结果:
import threading import time,random class mulitThraed(threading.Thread): def __init__(self,theadStr): threading.Thread.__init__(self) self.name=theadStr def run(self): for n in range(1,4): print("{0} {1}".format(threading.current_thread().getName(),str(n))) time.sleep(3) if __name__=='__main__': c_th1=mulitThraed("Hello1") c_th2=mulitThraed("Hello2") c_th1.start() c_th2.start() c_th1.join() c_th2.join() print('{0}线程结束'.format(threading.current_thread().getName()))
结果: Hello1 1 Hello2 1 Hello1 2 Hello2 2 Hello1 3 Hello2 3 MainThread线程结束
注上面两个程序运行结果在每次运行都可能会有差异(子线程并行运行),若将join()对象注释掉,就会导致主线程与子线程并行,若加上join()主线程会等待所有子线程结束后才开始,各个子线程之间不用相互等待,并行运行。
守护线程
对于守护线程,只要主程序执行完毕,不管子线程还有没有执行完程序都会退出。
在多线程开发中,如果子线程设定为了守护线程,守护线程会等待主线程运行完毕后被销毁。一个主线程可以设置多个守护线程,守护线程运行的前提是,主线程必须存在,如果主线程不存在了,守护线程会被销毁。
import threading import time,random def Test(strName): print("Thread :{0}".format(strName)) time.sleep(2) if __name__=="__main__": for n in range(1,4): t=threading.Thread(target=Test,args=("deamon {0}".format(n),)) t1=threading.Thread(target=Test,args=(n,)) t.daemon=True #设置为守护线程 t.start() t1.start() #常规线程 print("{0} 存活线程数:{1}".format(threading.current_thread().getName(),threading.active_count()))
结果:
Thread :deamon 1 Thread :1 Thread :deamon 2 Thread :2 Thread :deamon 3 Thread :3 MainThread 存活线程数:7