python--(十步代码学会线程)
一.线程的创建
Thread实例对象的方法 # isAlive(): 返回线程是否活动的. # getname(): 返回线程名. # setName(): 设置线程名. threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
from threading import Thread from multiprocessing import Process #第一种方法 def func(n): print(n) if __name__ == '__main__': t = Thread(target=func, args=("我是线程",)) t.start() # p = Process(target=func, args=("我是进程",)) # p.start() print("主进程结束.") #第二种方法 class MyThread(Thread): def run(self): print("辉哥牛逼") if __name__ == "__main__": t = MyThread() t.start() print("主线程结束")
import time from threading import Thread from multiprocessing import Process def func(n): num = 0 for n1 in range(n): num += n1 print("num",num) if __name__ == '__main__': t_s_t = time.time() t_list = [] for i in range(10): t = Thread(target=func, args=(10,)) t.start() #速度特别快 t_list.append(t) [tt.join() for tt in t_list] t_e_t = time.time() t_dif_t = t_s_t - t_e_t #获取了线程的执行时间 p_s_t = time.time() p_list = [] for ii in range(10): p = Process(target=func, args=(10,)) p.start() #速度非常快 p_list.append(p) [pp.join() for pp in p_list] p_e_t = time.time() #结束时间 p_dif_t = p_e_t - p_s_t #获取进程执行时间 print('线程>>>>', t_dif_t) print('进程....', p_dif_t) print('主线程结束')
线程的其他方法
# 线程的一些其他方法 # from threading import Thread # import threading # import time # from multiprocessing import Process # import os # # def work(): # import time # time.sleep(1) # print(threading.current_thread().getName()) #Thread-1 # print(threading.current_thread()) #Thtrad-1 # # if __name__ == '__main__': # #在主进程下开启线程 # t = Thread(target=work) # t.start() # # # print(threading.current_thread()) #主线程对象 # # print(threading.current_thread().getName()) #主线程名称 # # print(threading.current_thread().ident) #主线程ID # # print(threading.get_ident()) #主线程ID # # time.sleep(3) # print(threading.enumerate()) #连同主线程在内有两个运行的线程 # print(threading.active_count()) #进程数 # print("主线程/主进程")
二.数据共享
from threading import Thread from multiprocessing import Process num = 100 def func(): global num num = 0 if __name__ == '__main__': t = Thread(target=func,) t.start() t.join() print(num) # p = Process(target=func,) # p.start() # p.join() # print(num)
mport time from threading import Thread,Lock #演示共享资源的时候,数据不安全的问题 # num = 100 # def func(): # global num # num -= 1 # mid = num # mid = mid - 1 # time.sleep(0.00001) # num = mid # if __name__ == '__main__': # t_list = [] # for i in range(10): # t = Thread(target=func,) # t.start() # t_list.append(t) # [tt.join() for tt in t_list] # print("主进程>>>>", num) #通过锁来解决数据不安全的问题,线程模块里面引入的锁 num = 100 def func(t_lock): global num t_lock.acquire() mid = num mid = mid - 1 time.sleep(0.0001) num = mid t_lock.release() if __name__ == '__main__': t_lock = Lock() #锁对象(同步锁,互斥锁) t_list = [] for i in range(10): t = Thread(target=func,args=(t_lock,)) t.start() t_list.append(t) [tt.join() for tt in t_list] print("主进程>>>>",num)
三.守护进程
守护进程 :
主进程代码结束程序并没有结束,并且主进程还存在,进程等待其他的子进程执行结束以后,为子进程收尸,注意一个问题:主进程的代码运行结束守护进程跟着结束,
守护线程:
主线程等待所有非守护线程的结束才结束,主线程的代码运行结束,还要等待非守护线程的执行完毕.这个过程中守护线程还存在
1 import time 2 from threading import Thread 3 from multiprocessing import Process 4 def func1(n): 5 time.sleep(5) 6 print(n) 7 def func2(n): 8 time.sleep(3) 9 print(n) 10 if __name__ == '__main__': 11 # p1 = Process(target=func1,args=("我是子进程1号",)) 12 # #设置守护进程,在start之前加 13 # p1.start() 14 # p2 = Process(target=func2,args=("我是子进程2号",)) 15 # p2.daemon = True 16 # p2.start() 17 # print("子进程结束")
四.死锁现象
锁(同步锁互斥锁): 保证数据安全,但是牺牲了效率,同步执行锁内的代码
死锁现象 : 互相抢到了对方的需要的锁,导致双方相互等待,程序没法进行
解决死锁: 递归锁,RLock #可以多次acquire,通过一个计数器来记录被锁了多少次,只有计数器为0的时候,大 家才能继续抢锁
import time from threading import Thread,Lock class MyThread(Thread): def __init__(self,lockA,lockB): super().__init__() self.lockA = lockA self.lockB = lockB def run(self): self.f1() self.f2() def f1(self): self.lockA.acquire() print('我拿了A锁') self.lockB.acquire() print('我是一个很好的客户!') self.lockB.release() self.lockA.release() def f2(self): self.lockB.acquire() time.sleep(0.1) print('我拿到了B锁') self.lockA.acquire() print('我是一名合格的技师') self.lockA.release() self.lockB.release() if __name__ == '__main__': lockA = Lock() lockB = Lock() t1 = MyThread(lockA,lockB) t1.start() t2 = MyThread(lockA,lockB) t2.start() print('我是经理')
import time from threading import Thread,Lock,RLock #递归锁 class MyThread(Thread): def __init__(self,lockA,lockB): super().__init__() self.lockA = lockA self.lockB = lockB def run(self): self.f1() self.f2() def f1(self): self.lockA.acquire() print('我拿了A锁') self.lockB.acquire() print('我是一个很好的客户!') self.lockB.release() self.lockA.release() def f2(self): self.lockB.acquire() time.sleep(0.1) print('我拿到了B锁') self.lockA.acquire() print('我是一名合格的技师') self.lockA.release() self.lockB.release() if __name__ == '__main__': # lockA = Lock() # lockB = Lock() # lockA = lockB = Lock() #不要这么写,别自己玩自己,锁自己 lockA = lockB = RLock() t1 = MyThread(lockA,lockB) t1.start() t2 = MyThread(lockA,lockB) t2.start() print('我是经理')
五.信号量
信号量: 控制同时能够进入锁内去执行代码的线程数量(进程数量),维护了一个计数器,刚开始创建信号量的时候假如设置的是4个房间,进入一次acquire就减1 ,出来一个就+1,如果计数器为0,那么其他的任务等待,这样其他的任务和正在执行的任务是一个同步的状态,而进入acquire里面去执行的那4个任务是异步执行的.
import time from threading import Thread, Semaphore def func1(s): s.acquire() time.sleep(1) print('大宝剑!!!') s.release() if __name__ == '__main__': s = Semaphore(4) for i in range(10): t = Thread(target=func1,args=(s,)) t.start()
六.事件
# # 事件 # from threading import Thread,Event # e = Event() #e的状态有两种,False Ture,当事件对象的状态为False的时候,wait的位置会阻塞 # # e.set() #将事件对象的状态改为Ture # e.clear() #将事件对象的状态改为False # print("在这里等待") # e.wait() #阻塞 # print("还没好")
七.队列
mport queue #先进先出 FIFO # q=queue.Queue() # q.put('first') # q.put('second') # q.put('third') # # q.put_nowait() #没有数据就报错,可以通过try来搞 # print(q.get()) # print(q.get()) # print(q.get()) # # q.get_nowait() #没有数据就报错,可以通过try来搞 # ''' # first # second # third # ''' # 先进后出 # import queue # q = queue.LifoQueue() #队列类似于栈,先进后出的顺序 # q.put('first') # q.put('second') # q.put('third') # q.put_nowait() # print(q.get()) # print(q.get()) # print(q.get()) # # q.get_nowait() #没有数据就报错 # ''' # third # second # first # ''' # # 优先级队列 # import queue # q = queue.PriorityQueue() # #put进入一个元祖,元祖的第一个元素是优先级(通常是数字,也可以是非数字之间的比较,数字越小优先级越高 # q.put((-10,"a")) # q.put((-5,"a")) #负数也可以 # # # q.put((20,'b')) #如果第一个参数数字的优先级一样,那么按照后面的字符串acsii来排序 # # q.put((20,'c')) # # # q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典 # # q.put((20,('w',1))) #优先级相同的两个数据,他们后面的值必须是相同的数据类型才能比较,可以是元祖,也是通过元素的ascii码顺序来排序 # # print(q.get()) # print(q.get()) # """结果:数字越小优先级越高,优先级高的优先出队"""
八.线程池
concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor:线程池,提供异步调用 ProcessPoolExecutor: 进程池,提供异步调用 Both implement the same interface, which is defined by the abstract Executor class. #2 基本方法 #submit(fn, *args, **kwargs) 异步提交任务 #map(func, *iterables, timeout=None, chunksize=1) 取代for循环submit的操作 #shutdown(wait=True) 相当于进程池的pool.close()+pool.join()操作 wait=True,等待池内所有任务执行完毕回收完资源后才继续 wait=False,立即返回,并不会等待池内的任务执行完毕 但不管wait参数为何值,整个程序都会等到所有任务执行完毕 submit和map必须在shutdown之前 #result(timeout=None) 取得结果 #add_done_callback(fn) 回调函数
# 线程池 # import time # from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor # #ProcessPoolExecutor 进程池 # from threading import current_thread # # def func(n): # time.sleep(1) # # print(n,current_thread().ident) # return n**2 # if __name__ == '__main__': # t_p = ThreadPoolExecutor(max_workers = 4) # map_res = t_p.map(func,range(10)) #异步执行的,map自带join功能 # print(map_res) # print([i for i in map_res])
线程池的一些其他方法
# 线程池的一些其他方法 # import time # from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor # from threading import current_thread # def func(n): # time.sleep(1) # #print(n,current_thread().ident) # return n**2 # def func2(n): # print(n) # if __name__ == '__main__': # t_p = ThreadPoolExecutor(max_workers=4) # t_p_list = [] # for i in range(10): # res_obj = t_p.submit(func, i) #异步提交了这10个任务 # # res_obj.result() #他和get一样 # t_p_list.append(res_obj) # t_p.shutdown() #close + join 等待全部完成之后关闭子线程,防止后面数据进入 # # print('t_res_list',t_p_list) # for e_res in t_p_list: # print(e_res.result())
九.回调函数
rom concurrent.futures import ThreadPoolExecutor from threading import current_thread def func(n): time.sleep(1) print(n**2) # print(n,current_thread().getName()) # return n**2 def func2(n): # print("current_thread>>>>",current_thread().getName()) print(n.result()) #result() 相当于 get() if __name__ == '__main__': t_p = ThreadPoolExecutor(max_workers=1) for i in range(3): t_p.submit(func, i).add_done_callback(func2) print('主进程结束')
十.GIL锁
#保证数据安全,锁的是整个线程,每次只能有一个线程使用cpu,是CPython解释器的特性