线程相关内容
1.线程: 是cpu执行程序的最小单元,一份进程中可以包含多个线程,开辟线程时无需重新分配资源,子线程跟主线程共享资源。
from multiprocessing import Process from threading import Thread import time # 进程并发 def func(i): print(i) if __name__ == "__main__": lst = [] time1 = time.time() for i in range(100): p = Process(target=func,args=(i,)) p.start() lst.append(p) for j in lst: j.join() time2 = time.time() print(time2-time1) # 2.086568593978882 from multiprocessing import Process from threading import Thread import time # 线程并发 def func(i): print(i) if __name__ == "__main__": lst = [] time1 = time.time() for i in range(100): t = Thread(target=func,args=(i,)) t.start() lst.append(t) for j in lst: j.join() # 线程也是异步的 time2 = time.time() print(time2-time1) # 0.01492619514465332 因无需再分配资源,所以线程速度大大快于进程
1.1 线程之间共享数据
from threading import Thread a = 100 def func(): global a a -= 1 if __name__ == "__main__": for i in range(10): t = Thread(target=func) t.start() print(a) # 90
1.2 用类定义线程
from threading import Thread class Mythread(Thread): def __init__(self,args): self.args = args super().__init__() # 若有参数则要通过super()调父类里面的init方法 def run(self): # 必须命名为run()方法 print("用类定义的线程",self.args) if __name__ == "__main__": t = Mythread(888) t.start() # 用类定义的线程 888
1.3 线程相关的函数
from threading import Thread import time def func(): time.sleep(1) print(111) # (1) is_alive(): 判断线程是否还存在 if __name__ == "__main__": t = Thread(target=func) t.start() res = t.is_alive() print(res) # True # (2) setName():设置线程的名字 if __name__ == "__main__": t = Thread(target=func) t.start() t.setName("8号") print(t) # <Thread(8号, started 5880)> # (3) getName(): 获取线程名字 if __name__ == "__main__": t = Thread(target=func) t.start() t.setName("8号") print(t.getName()) # 8号 # (4) currentThread().ident:查看线程id号 from threading import currentThread #需要引入currentThread if __name__ == "__main__": t = Thread(target=func) t.start() res = currentThread().ident print(res) # 3380 # (5) enumerate():返回正在运行的线程列表 from threading import enumerate if __name__ == "__main__": t = Thread(target=func) t.start() lst = enumerate() print(lst) # [<_MainThread(MainThread, started 9096)>, <Thread(Thread-1, started 14956)>] # (6) activeCount():返回正在运行的线程数量 from threading import enumerate,activeCount if __name__ == "__main__": t = Thread(target=func) t.start() res = activeCount() # 方式一 print(res) # 2 lst = enumerate() # 方式二 print(len(lst)) # 2
1.4 守护线程:守护的是所有的子线程,等所有子线程都执行完后,守护线程也会被终止
from threading import Thread import time def func1(): time.sleep(0.5) print("老二,你结束没?") time.sleep(0.5) print("我要关掉了") def func2(): time.sleep(1.5) print("大哥,等我一会") time.sleep(1) if __name__ == "__main__": t1 = Thread(target=func1) t1.setDaemon(True) t1.start() t2 = Thread(target=func2) t2.start() t2.join() print("臭小子,还有你们的老父亲我呢") time.sleep(1) print("OK,回家") # 在主线程和func2都结束后,func1结束,程序结束
1.5 Lock:上锁,保护数据安全
from threading import Thread,Lock import time money = 1000000 def func(lock): global money with lock: for i in range(100000): money -= 1 if __name__ == "__main__": lock = Lock() lst = [] for i in range(10): t = Thread(target=func,args=(lock,)) t.start() lst.append(t) print("败家子儿,我的一百万,被你们折腾得就剩{}了".format(money)) for j in lst: j.join() print("败家子儿,我的一百万,被你们折腾得就剩{}了".format(money)) print("还不赶紧还给我") def func(lock): global money with lock: for i in range(100000): money += 1 if __name__ == "__main__": lock = Lock() lst = [] for i in range(10): t = Thread(target=func,args=(lock,)) t.start() lst.append(t) print("还给你,有啥了不起,给你{}".format(money)) for j in lst: j.join() print("对,都还给你,{}元".format(money))
1.6 信号量Semaphore: 线程中控制锁的数量
from threading import Thread,Semaphore import time def func(sem,i): sem.acquire() print("这是"+str(i)) time.sleep(1) sem.release() if __name__ == "__main__": sem = Semaphore(3) for i in range(10): t = Thread(target=func,args=(sem,i)) t.start() # with语法 from threading import Thread,Semaphore import time def func(i): with sem: print("给我食物,给我钱") print(i) time.sleep(2) if __name__ == "__main__": sem = Semaphore(2) lst1 = [] lst = ["肉包子", "200万", "排骨汤", "腊肠", "腊鱼", "花生米", "酸菜鱼", "100万"] for i in lst: t = Thread(target=func,args=(i,)) t.start() lst1.append(t) for j in lst1: j.join()
1.7:
python中的线程可以并发,但是不能并行(同一个进程下的多个线程不能分开被多个cpu同时执行)
原因:
全局解释器锁(Cpython解释器特有) GIL锁:同一时间,一个进程下的多个线程只能被一个cpu执行
python是解释型语言,执行一句编译一句,而不是一次性全部编译成功,不能提前规划,都是临时调度
容易造成cpu执行调度异常.所以加了一把锁叫GIL
想要并行的解决办法:
(1)用多进程间接实现线程的并行
(2)换一个Pypy,Jpython解释器
程序分为计算密集型和io密集型
对于计算密集型程序会过度依赖cpu,但网页,爬虫,OA办公,这种io密集型的程序里,python绰绰有余