线程
一、线程
1.什么是线程?
首先我们要知道,进程线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物
进程:资源单位
线程:执行单位
将内存比喻成工厂
那么进程就相当于是工厂里面的车间
而你的线程就相当于是车间里面的流水线
ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中提供代码运行所需要的资源
2.为什么要有线程
开进程
1.申请内存空间 耗资源
2.“拷贝代码” 耗资源
开线程
一个进程内可以起多个线程,并且线程与线程之间数据是共享的
PS:开启线程的开销要远小于开启进程的开销
二、创建进程的两种方式
方式一:
1 from threading import Thread 2 import time 3 4 def task(name): 5 print('%s is running'%name) 6 time.sleep(3) 7 print('%s is over'%name) 8 9 #开线程不需要在__main__代码块中,但是出于习惯,我们可以写在__main__代码块中 10 t = Thread(target=task,args=('jason',)) 11 t.start() #告诉操作系统开辟一个线程 12 #小的代码执行完,线程就已经开启了 13 print('主')
方式二:
1 from threading import Thread 2 import time 3 4 class MyThread(Thread): 5 def __init__(self,name): 6 super().__init__() 7 self.name = name 8 9 def run(self): 10 print('%s is running'%(self.name)) 11 time.sleep(3) 12 print('%s is over'%(self.name)) 13 14 t = MyThread('jason') 15 t.start() 16 print('主')
三、线程对象及其他方法
1 from threading import Thread,current_thread,active_count 2 import os 3 import time 4 5 def task(name,i): 6 print('%s is running'%name) 7 print('字current_thread:',current_thread().name) 8 print('子',os.getpid()) 9 time.sleep(i) 10 print('%s is over'%name) 11 12 t = Thread(target=task,args=('jason',1)) 13 t1 = Thread(target=task,args=('tank',2)) 14 t.start() 15 t1.start() 16 t1.join() #主线程等待子线程运行完毕 17 print('当前正在活跃的线程数',active_count()) 18 print('主') 19 print('主current_thread:',current_thread().name) 20 print('主',os.getpid())
四、守护线程
1 from threading import Thread,current_thread 2 import time 3 4 def task(i): 5 print(current_thread().name) 6 time.sleep(i) 7 print('GG') 8 9 t = Thread(target=task,args=(1,)) 10 t.daemon = True 11 t.start() 12 print('主')
主线程的结束也就意味着进程的结束
主线程必须等待其他非守护线程的结束才能结束,原因是:因为子线程在运行时需要使用进程中的资源,而主线程一旦结束了资源也就销毁了
五、线程间通信
1 from threading import Thread 2 3 money = 666 4 5 def task(): 6 global money 7 money = 999 8 9 t = Thread(target=task) 10 t.start() 11 t.join() 12 print(money) 13 14 ''' 15 事实证明线程与线程之间可以进行通信 16 '''
六、互斥锁
1 from threading import Thread,Lock 2 import time 3 4 n = 100 5 6 def task(mutex): 7 global n 8 mutex.acquire() 9 num = n 10 time.sleep(0.1) 11 n = num - 1 12 mutex.release() 13 14 t_list = [] 15 mutex = Lock() 16 for i in range(100): 17 t = Thread(target=task,args=(mutex,)) 18 t.start() 19 t.join() 20 print(n)
七、小例题及分析
1 from threading import Thread 2 from multiprocessing import Process 3 import time 4 def foo(): 5 print(123) 6 time.sleep(1) 7 print("end123") 8 9 def bar(): 10 print(456) 11 time.sleep(3) 12 print("end456") 13 14 if __name__ == '__main__': 15 t1=Thread(target=foo) 16 t2=Thread(target=bar) 17 t1.daemon=True 18 t1.start() 19 t2.start() 20 print("main-------")
结果为:
''' 123 456 main------- end123 end456 '''
分析:
首先创建两个线程对象,将t1设置为守护线程,意味着主进程执行完毕后,就会一起终止t1,然后,执行t1线程,紧接着执行t2线程,所以首先打印:123,456。然后根据主线程代码打印了:main-----。此时t1暂停一秒后执行了打印:end123。t1运行结束,但是此时t2并未运行结束,所以主线程会继续等待t2线程运行结束再结束执行。3秒过后t2执行打印:end456。t2也运行结束,主线程随之终止。