1、应用程序
import threading print('666') def func(arg): print(arg) t = threading.Thread(target=func) t.start() print('end')
2、线程的使用
import threading 1.线程的基本使用 def func(arg): print(arg) t = threading.Thread(target=func,args=(11,)) t.start() print(123) 2.主线程默认等子线程执行完毕 import time def func(arg): time.sleep(arg) print(arg) t1 = threading.Thread(target=func,args=(3,)) t1.start() t2 = threading.Thread(target=func,args=(9,)) t2.start() print(123) 3.主线程不再等,主线程终止则所有子线程终止 import time def func(arg): time.sleep(2) print(arg) t1 = threading.Thread(target=func,args=(3,)) t1.setDaemon(True) t1.start() t2 = threading.Thread(target=func,args=(9,)) t2.setDaemon(True) t2.start() print(123) 4.开发者可以控制主线程等待子线程(最多等待时间) import time def func(arg): time.sleep(0.01) print(arg) print('创建子线程t1') t1 = threading.Thread(target=func,args=(3,)) t1.start() # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。 # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。 t1.join(2) print('创建子线程t2') t2 = threading.Thread(target=func,args=(9,)) t2.start() t2.join(2) # 让主线程在这里等着,等到子线程t2执行完毕,才可以继续往下走。 print(123) 4.线程名称 def func(arg): # 获取当前执行该函数的线程的对象 t = threading.current_thread() # 根据当前线程对象获取当前线程名称 name = t.getName() print(name,arg) t1 = threading.Thread(target=func,args=(11,)) t1.setName('侯明魏') t1.start() t2 = threading.Thread(target=func,args=(22,)) t2.setName('刘宁钱') t2.start() print(123) 5.线程本质 # 先打印:11?123? def func(arg): print(arg) t1 = threading.Thread(target=func,args=(11,)) t1.start() # start 是开始运行线程吗?不是 # start 告诉cpu,我已经准备就绪,你可以调度我了。 print(123) 6.补充:面向对象版本的多线程 # 多线程方式:1 (常见) def func(arg): print(arg) t1 = threading.Thread(target=func,args=(11,)) t1.start() # 多线程方式:2 class MyThread(threading.Thread): def run(self): print(11111,self._args,self._kwargs) t1 = MyThread(args=(11,)) t1.start() t2 = MyThread(args=(22,)) t2.start() print('end')
3、多线程
import threading 1. 计算密集型多线程无用 v1 = [11,22,33] # +1 v2 = [44,55,66] # 100 def func(data,plus): for i in range(len(data)): data[i] = data[i] + plus t1 = threading.Thread(target=func,args=(v1,1)) t1.start() t2 = threading.Thread(target=func,args=(v2,100)) t2.start() 2. IO操作 多线程有用 import threading import requests import uuid url_list = [ 'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg', 'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg', 'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg', ] def task(url): ret = requests.get(url) file_name = str(uuid.uuid4()) + '.jpg' with open(file_name, mode='wb') as f: f.write(ret.content) for url in url_list: t = threading.Thread(target=task,args=(url,)) t.start()
4、多线程的问题
# by luffycity.com import time import threading lock = threading.RLock() n = 10 def task(i): print('这段代码不加锁',i) lock.acquire() # 加锁,此区域的代码同一时刻只能有一个线程执行 global n print('当前线程',i,'读取到的n值为:',n) n = i time.sleep(1) print('当前线程',i,'修改n值为:',n) lock.release() # 释放锁 for i in range(10): t = threading.Thread(target=task,args=(i,)) t.start()
5、区别
Python多线程情况下: - 计算密集型操作:效率低。(GIL锁) - IO操作: 效率高 Python多进程的情况下: - 计算密集型操作:效率高(浪费资源)。 不得已而为之。 - IO操作: 效率高 (浪费资源)。 以后写Python时: IO密集型用多线程: 文件/输入输出/socket网络通信 计算密集型用多进程。 扩展: Java多线程情况下: - 计算密集型操作:效率高。 - IO操作: 效率高 Python多进程的情况下: - 计算密集型操作:效率高(浪费资源)。 - IO操作: 效率高 浪费资源)。 Python中线程和进程(GIL锁) GIL锁,全局解释器锁。用于限制一个进程中同一时刻只有一个线程被cpu调度。 扩展:默认GIL锁在执行100个cpu指令(过期时间)。