线程

mac2022-06-30  294

什么是线程

开启线程的两种方式

和开启进程的两种方式相似,只不过改一下导入的模块

进程与线程之间的区别:

开进程的开销远大于开线程 同一进程内多个线程共享该进程的内存空间 Pid相同

 

Tread 方法

from threading import Thread,currentThread,active_count,enumerateimport timedef task():print('%s is running'% currentThread().getName()) time.sleep(1)print('%s is done'% currentThread().getName())if __name__=='__main__': t = Thread(target=task,name='线程1') # name 设置线程名t.start() t.setName('线程-1') # 设置线程名print(t.getName()) # 获取线程名print(t.is_alive(),t.isAlive()) t.join() # 等待线程执行完print(t.isAlive())print(currentThread().getName()) # 获取当前线程,在主线程下获取的就是主线程名currentThread().setName('main线程') # 设置当前线程名print('主线程',currentThread().getName())print(active_count()) # 先导入active_count 查看活跃线程数目print(enumerate()) # 先导入enumerate 查看线程

 

守护线程

from threading import Threadimport timedef foo():print(123) time.sleep(1)print('end123')def bar():print(456) time.sleep(3)print('end456')if __name__=='__main__': t1 = Thread(target=foo) t2 = Thread(target=bar) t1.setDaemon(True) # 等价于t1.daemon = Truet1.start() t2.start()print('--main--')

守护线程等到非守护线程结束才结束。

互斥锁

from threading import Thread,Lockimport timen = 100def task():global n mutex.acquire() temp = n time.sleep(0.1) n = temp - 1mutex.release()if __name__ == '__main__': t_list = [] mutex = Lock()for i in range(100): t = Thread(target=task,) t.start() t_list.append(t)for i in t_list: i.join()print(n)

 

0

 

死锁

当两个线程互相争取对方现有的锁,就会造成死锁的现象。

递归锁

可以连续acquire多次,每acquire一次计数器加1,只有计数器为0时,其他线程才可以抢到该锁。

from threading import Thread,RLockimport timemutexA = mutexB = RLock()class MyThread(Thread):def run(self):self.f1()self.f2()def f1(self): mutexA.acquire()print('%s 拿到A锁'%self.name) mutexB.acquire()print('%s 拿到B锁' % self.name) mutexB.release() mutexA.release()def f2(self): mutexB.acquire()print('%s 拿到B锁' % self.name) time.sleep(3) mutexA.acquire()print('%s 拿到A锁' % self.name) mutexA.release() mutexB.release()if __name__=='__main__':for i in range(5): t = MyThread() t.start()

 

Thread-1 拿到A

Thread-1 拿到B

Thread-1 拿到B

Thread-1 拿到A

Thread-2 拿到A

Thread-2 拿到B

Thread-3 拿到A

Thread-3 拿到B

Thread-3 拿到B

Thread-3 拿到A

Thread-5 拿到A

Thread-5 拿到B

Thread-2 拿到B

Thread-2 拿到A

Thread-4 拿到A

Thread-4 拿到B

Thread-5 拿到B

Thread-5 拿到A

Thread-4 拿到B

Thread-4 拿到A

信号量

有10个人上公共厕所,公共厕所只有五个坑,同一时间最多可以有五个人同时上厕所。

from threading import Thread,currentThread,Semaphoreimport time,randomsem = Semaphore(5)def task():# sem.acquire() # print('%s get'% currentThread().getName()) # sem.release()with sem: # 与上边等价,这种方式更简洁print('%s get' % currentThread().getName()) time.sleep(random.randint(1,5))print('%s out' % currentThread().getName())if __name__=='__main__':for i in range(10): t = Thread(target=task) t.start()

 

Thread-1 get

Thread-2 get

Thread-3 get

Thread-4 get

Thread-5 get

Thread-5 out

Thread-6 get

Thread-6 out

Thread-7 get

Thread-1 out

Thread-8 get

Thread-3 out

Thread-2 out

Thread-9 get

Thread-10 get

Thread-7 out

Thread-4 out

Thread-8 out

Thread-9 out

Thread-10 out

Event

from threading import Thread,Eventimport timeevent = Event()def student(name):print('%s 正在听课'% name) event.wait() # 括号里面加上数字就是等待时间print('%s 课间活动'% name)def teacher(name):print('%s 正在授课'%name) time.sleep(7)print('%s 下课' % name) time.sleep(0.1) event.set()if __name__ == '__main__': s1 = Thread(target=student,args=('rose',)) s2 = Thread(target=student, args=('lucy',)) s3 = Thread(target=student, args=('lily',)) t = Thread(target=teacher, args=('luli',)) s1.start() s2.start() s3.start() t.start()

 

rose 正在听课

lucy 正在听课

lily 正在听课

luli 正在授课

luli 下课

rose 课间活动

lily 课间活动

lucy 课间活动

 

 

# from threading import Thread,Event# import time# event = Event()## def student(name):# print('%s 正在听课'% name)# event.wait() # 括号里面加上数字就是等待时间# print('%s 课间活动'% name)## def teacher(name):# print('%s 正在授课'%name)# time.sleep(7)# print('%s 下课' % name)# time.sleep(0.1)# event.set()### if __name__ == '__main__':# s1 = Thread(target=student,args=('rose',))# s2 = Thread(target=student, args=('lucy',))# s3 = Thread(target=student, args=('lily',))## t = Thread(target=teacher, args=('luli',))## s1.start()# s2.start()# s3.start()# t.start()from threading import Thread,Event,currentThreadimport timeevent = Event()def conn(): n=0while not event.is_set(): # event 是否被设置if n == 3:print('%s try too many times'% currentThread().getName())returnn += 1event.wait(0.5)print('%s try %s time'%(currentThread().getName(),n))print('%s is connected'%currentThread().getName())def check():print('%s is checking'%currentThread().getName()) time.sleep(5) event.set()if __name__ =='__main__':for i in range(3): con = Thread(target=conn) con.start() check = Thread(target=check) check.start()

 

Thread-4 is checking

Thread-2 try 1 time

Thread-1 try 1 time

Thread-3 try 1 time

Thread-1 try 2 time

Thread-3 try 2 time

Thread-2 try 2 time

Thread-1 try 3 time

Thread-1 try too many times

Thread-2 try 3 time

Thread-3 try 3 time

Thread-3 try too many times

Thread-2 try too many times

 

定时器

验证码刷新

from threading import Timerimport randomclass Code:def __init__(self):self.make_cache()def make_cache(self,interval=10):self.cache = self.make_code()print(self.cache)self.t = Timer(interval,self.make_cache) # 这个地方是函数名,如果是函数名()会报错self.t.start()def make_code(self,): res = ''for i in range(4): s1=str(random.randint(0,9)) s2 = chr(random.randint(65,90)) # 大写字母res += random.choice([s1,s2])return resdef check(self):while True: code = input('验证码:').strip()print('验证码 %s'%self.cache)print('输入:%s'% code.upper())if code.upper() == self.cache: # 不用区分大小写print('正确')self.t.cancel()breakobj = Code()obj.check()

 

 

线程queue

 

 

多线程实现并发套接字通信

 

进程池线程池

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutorimport os,time,randomdef task(name):print('name:%s pid:%s'%(name,os.getpid())) time.sleep(random.randint(1,3))if __name__=='__main__': pool = ThreadPoolExecutor(4)for i in range(10): pool.submit(task,'id %s'%i) pool.shutdown() # 等待进程执行结束print('主')

 

name:id 0 pid:8892

name:id 1 pid:8892

name:id 2 pid:8892

name:id 3 pid:8892

name:id 4 pid:8892

以上代码实现的是线程池,如果实现进程池只要改一行代码:

Pool = ProcessPoolExecutor(4)就ok了

 

同步调用异步调用

同步调用

from concurrent.futures import ThreadPoolExecutorimport time,randomdef work(name):print('%s is working'%name) time.sleep(random.randint(2,5)) res = random.randint(8,24)return {'name':name,'hours':res}def count(res): name = res['name'] num = res['hours']*10print('%s 制造了%s个艺术品'%(name,num))if __name__ =='__main__': pool = ThreadPoolExecutor(10) worker1 = pool.submit(work,'1').result() count(worker1) worker2 = pool.submit(work, '2').result() count(worker2) worker3 = pool.submit(work, '3').result() count(worker3)

 

1 is working

1 制造了120个艺术品

2 is working

2 制造了240个艺术品

3 is working

3 制造了170个艺术品

 

异步调用

from concurrent.futures import ThreadPoolExecutorimport time,randomdef work(name):print('%s is working'%name) time.sleep(random.randint(2,5)) res = random.randint(8,24)return {'name':name,'hours':res}def count(res): res = res.result() # future对象此时已经执行完毕,获取future对象的结果name = res['name'] num = res['hours']*10print('%s 制造了%s个艺术品'%(name,num))if __name__ =='__main__': pool = ThreadPoolExecutor(10) pool.submit(work,'1').add_done_callback(count) # 调用count方法并把结果future对象传给方法pool.submit(work, '2').add_done_callback(count) pool.submit(work, '3').add_done_callback(count)

 

1 is working

2 is working

3 is working

3 制造了220个艺术品

2 制造了200个艺术品

1 制造了170个艺术品

转载于:https://www.cnblogs.com/yuliangkaiyue/p/9661270.html

最新回复(0)