一、线程理论
1、什么是线程
进程:资源单位
线程:执行单位
注意:每一个进程中都会自带一个线程
拿一个工厂中车间里的流水线作比喻
进程比喻为车间
线程比喻为流水线
操作系统比喻为工厂
2、为什么要有线程
开一个进程: 申请内存空间 --->>> 耗时 将代码拷贝到申请的内存空间中 --->>> 耗时 开线程:不需要申请内存空间 不需要拷贝代码
3、进程vs线程
①同一进程内的多个线程共享该进程内的资源,不同进程内的线程资源是隔离的
②创建线程的开销比创建进程小
二、创建线程的两种方式
1、方式一
from threading import Thread import time def task(name): print('%s is running' % name) time.sleep(1) if __name__ == '__main__': t = Thread(target=task, args=('egon',)) t.start() # 开启线程的速度非常快,几乎代码执行完线程就已经开启 print('主') # 结果为 egon is running 主
2、方式二
from threading import Thread import time class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self): print('%s is running' % self.name) time.sleep(1)if __name__ == '__main__': t = MyThread('jason') t.start() print('主') # 结果为 jason is running 主
三、线程之间数据共享
from threading import Thread x = 100 def task(): global x x = 20if __name__ == '__main__': t = Thread(target=task) # 实例化一个对象 t.start() t.join() print(x) # 结果为 20
四、线程对象其他方法
from threading import Thread, current_thread, active_count import os import time def task(name): print('%s is running' %name, os.getpid(), current_thread().name) time.sleep(2) print('%s is over' % name) def info(name): print('%s is running' % name, os.getpid(), current_thread().name) time.sleep(2) print('%s is over' % name) if __name__ == '__main__': t1 = Thread(target=task, args=('jerry',)) t2 = Thread(target=info, args=('tom',)) t1.start() t2.start() t1.join() print(active_count()) # 当前存活的线程数 print(os.getpid()) # id号 print(current_thread().name) # 线程名字 # 结果为 jerry is running 7448 Thread-1 tom is running 7448 Thread-2 jerry is over 2 7448 MainThread tom is over
五、守护线程
主线程必须等待所有非守护线程的结束才能结束
from threading import Thread import time def task(name): print('%s is running' % name) time.sleep(1) if __name__ == '__main__': t = Thread(target=task, args=('jerry',)) t.daemon = True # t.daemon = True: 主线程运行完不会检查子线程程的状态(是否执行完),直接结束进程; t.start() print('主线程') # 结果为 jerry is running 主线程
六、线程互斥锁
from threading import Thread, Lock import time mutex = Lock() # 涉及到多个线程或者进程操作同一份数据的时候,通常都需要将并行、并发变成串行,虽然牺牲了效率,但是提升了数据的安全性
n = 50
def task(): global n mutex.acquire() tmp = n time.sleep(0.1) # 模拟io延迟 n = tmp - 1 mutex.release() t_list = [] for i in range(50): t = Thread(target=task) t.start() t_list.append(t) for t in t_list: t.join() print(n) # 结果为0