多线程-互斥锁或死锁
1.简单的多线程:
import threading import time def say(name): print('%s 子线程 start ' % name) time.sleep(10) print('%s 子线程 stop'%name) global a a='chenwei' if __name__=='__main__': print('___主线程开始___') t = threading.Thread(target=say,args=('eve',)) t.setName("线程的名字") t.setDaemon(True)#把主线程设置为守护线程(默认为False),若主线程结束了_不管子线程是否执行完成都会一并与主线程退出(必须在start执行使用setDaemon) aa=t.start() print('___主线程先走一步___') print(t.getName())#获取线程名字 #t.join()#等待子线程执行结束后,在执行主线程,,也可以设置超时时间join(3) print('___主线程结束___') ''' t.setDaemon(True)#把主线程设置为守护线程(默认为False),若主线程结束了_不管子线程是否执行完成都会一并与主线程退出(必须在start执行使用setDaemon) t.setDaemon(False)#主线程执行不会等待子线程,当主线程执行完毕后会等待子线程 '''
2.多线程-死锁:
#!/usr/bin/env python # -*- coding: utf-8 -*- import threading import time #———————————————————————————————多线程-互斥锁或死锁———————————————————————————————————————— chen=1 num = 0 def run(n): global num suo1=nutex.acquire()#上锁1(上锁后资源被锁定,其他线程用不了) if suo1: print('锁1存在') nutex.release()#解锁1(上锁前需要前解开) #当在一个锁的内部创建另外一个锁,而原来的锁没有解开就会死锁(程序执行到内锁就僵死了) suo2=suo.acquire()#上锁2 if suo2: print('锁2存在') for i in range(1000000): num += 1 #suo.release()#解锁2(若不解锁suo,那么线程2将会变成死锁,程序将卡死) print ("num1:", num) def test(m): global num suo.acquire()#上锁(当上一个锁被解开后才能上锁) for i in range(1000000): num += 1 suo.release()#解锁 print ("num2:", num) #创建两把锁 nutex=threading.Lock()#创建锁对象 suo=threading.Lock()#创建锁对象 t = threading.Thread(target=run, args=('a',))#这是随便传的值 t.start() t = threading.Thread(target=test, args=('b',))#这是随便传的值 t.start() #t.join() print ("num:", num)
3.在主线程中直接终止子线程:
#!/usr/bin/env python # encoding: utf-8 import threading import time import sys import ctypes import inspect def say(name): print('%s 子线程 start ' % name) time.sleep(5) print('%s 子线程 stop'%name) global a a='chenwei' def __async_raise(thread_Id, exctype): #在子线程内部抛出一个异常结束线程 #如果线程内执行的是unittest模块的测试用例, 由于unittest内部又异常捕获处理,所有这个结束线程 #只能结束当前正常执行的unittest的测试用例, unittest的下一个测试用例会继续执行,只有结束继续 #向unittest中添加测试用例才能使线程执行完任务,然后自动结束。 thread_Id = ctypes.c_long(thread_Id) if not inspect.isclass(exctype): exctype = type(exctype) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_Id, ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_Id, None) raise SystemError("PyThreadState_SEtAsyncExc failed") def terminator(thread): #结束线程 __async_raise(thread.ident, SystemExit) if __name__=='__main__': print('___主线程开始___') t = threading.Thread(target=say,args=('eve',)) t.setName("thread_01")#设置子线程名字 t.start()#启动子线程 print('___主线程先走一步___') print(t.getName())#获取线程名字 #t.join()#等待子线程执行结束后,在执行主线程,,也可以设置超时时间join(3) terminator(t)#在主线程中直接终止子线程 print('___主线程结束___')
4.子线程制造数据给主线程:
#!/usr/bin/env python # encoding: utf-8 import time import ctypes import inspect import random import threading ###_____________________________________________子线程制造数据给主线程__________________________________________________________ ''' 应用场景:主线程在android设备上执行业务操作、子线程需要记录android设备的cpu、内存等信息,在主线程执行后需要子线程的监控数据 ''' def __async_raise(thread_Id, exctype): #在子线程内部抛出一个异常结束线程 #如果线程内执行的是unittest模块的测试用例, 由于unittest内部又异常捕获处理,所有这个结束线程 #只能结束当前正常执行的unittest的测试用例, unittest的下一个测试用例会继续执行,只有结束继续 #向unittest中添加测试用例才能使线程执行完任务,然后自动结束。 thread_Id = ctypes.c_long(thread_Id) if not inspect.isclass(exctype): exctype = type(exctype) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_Id, ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_Id, None) raise SystemError("PyThreadState_SEtAsyncExc failed") def terminator(thread): #结束子线程 __async_raise(thread.ident, SystemExit) chen=[]#接收子线程制造的数据 def say(name): print('%s 子线程 start ' % name) time.sleep(2) print('%s 子线程 stop'%name) while True: time.sleep(2) number=random.randint(10,100)#随机数 print('子线程循环中...........') chen.append(number) if __name__=='__main__': print('___主线程开始___') t = threading.Thread(target=say,args=('eve',)) t.setName("thread_01")#设置子线程名字 t.start()#启动子线程 print('___主线程先走一步___') print('子线程的名字:',t.getName())#获取线程名字 #t.join()#等待子线程执行结束后,在执行主线程,,也可以设置超时时间join(3) #主线程 for i in range(10): time.sleep(3) print('主线程执行中,使用循环代替执行操作{}'.format(i)) terminator(t)#在主线程中直接终止子线程 print('chen的值为:',chen) print('___主线程结束___')
5.终止子线程的方法:
#!/usr/bin/env python # encoding: utf-8 import os import time import threading import threading,time ''' 这里重点介绍一下第二种方法,某些时候第一种方法不适用,会报错。例如开了一个线程,在线程内部又开了一个线程,此时关闭第一个线程就会报如下错误。 raise ValueError("invalid thread id") ValueError: invalid thread id ''' #________________________________________________________________________方法一_________________________________________________________ def stop_thread(thread): import inspect import ctypes tid = thread.ident exctype = SystemExit """raises the exception, performs cleanup if needed""" tid = ctypes.c_long(tid) if not inspect.isclass(exctype): exctype = type(exctype) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: # """if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect""" ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed") def serial_read(delay): while(1): time.sleep(delay) print('111') pass try: myThread = threading.Thread(target=serial_read,args=(1,)) myThread.start() except: print('error') print('222') time.sleep(10) stop_thread(myThread) #_____________________________________________________________________________________________方法二___________________________________________________________________ class StoppableThread(threading.Thread): def __init__(self, *args, **kwargs): super(StoppableThread, self).__init__(*args, **kwargs) self._stop_event = threading.Event() def stop(self): self._stop_event.set() def stopped(self): return self._stop_event.is_set() def run(self): print("{}开始运行子线程....".format(os.getpid())) while True: print("子线程循环等待.....") time.sleep(1) if self.stopped(): # 做一些必要的收尾工作 break if __name__ == "__main__": print("开始运行主线程..........") t = StoppableThread() t.start() time.sleep(10) t.stop()#主动停止子线程 #t.join()#等待子线程结束后在执行主线程 print("主线程停止运行") #___________________________________________________________________方法三___________________________________________________________________________ import threading import inspect import ctypes import time def _async_raise(tid, exctype): if not inspect.isclass(exctype): raise TypeError("Only types can be raised (not instances)") res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0) raise SystemError("PyThreadState_SetAsyncExc failed") class ThreadWithExc(threading.Thread): def _get_my_tid(self): if not self.isAlive(): raise threading.ThreadError("the thread is not active") if hasattr(self, "_thread_id"): return self._thread_id for tid, tobj in threading._active.items(): if tobj is self: self._thread_id = tid return tid raise AssertionError("could not determine the thread's id") def raiseExc(self, exctype): _async_raise(self._get_my_tid(), exctype ) def work(): try: while True: print('子线程work...........') time.sleep(1) except Server.ThreadStopped: pass print('子线程退出............') class Server: class ThreadStopped(Exception): pass def __init__(self): self.thread = ThreadWithExc(target=work) def start(self,device,name): self.thread.start() def stop(self): # _async_raise(self.thread.raiseExc(TypeError)) self.thread.raiseExc(self.ThreadStopped) if __name__ == '__main__': print('主线程开始........') server = Server() server.start('chenwei','123456789') for i in range(10): print('主线程循环等待中..........') time.sleep(1) server.stop()
6.多进程操作接口
import requests import json from concurrent.futures import ThreadPoolExecutor def delete(id): url = "https://pet-im-app-server.bndxqc.com/label/delete-label" payload = json.dumps({"id": id}) headers = { 'Authorization': 'Bearer eyJhbGciOiJhn2B5y7JtxM', 'Tenantid': '2951baabc1c442cf901402bd0a34d682', 'Content-Type': 'application/json', 'Accept': '*/*', 'Host': 'pet-im-app-server.bndxqc.com', 'Connection': 'keep-alive' } response = requests.post(url, headers=headers, data=payload) return response.text # 返回响应内容 def worker(idlist, max_workers=4): with ThreadPoolExecutor(max_workers=max_workers) as executor: # 使用executor.map并行执行delete函数 futures = executor.map(delete, idlist) for future in futures: print(future) # 打印每个响应内容
#需要操作的id idlist = idlist=[ "d016d149-f173-45ed-b298-9b14c87ad10f", "e38d599b-d4b9-4057-aa40-b0feb73f36c8", "e6801319-4d43-4d52-a164-3933c2ff021e", "e70d74c8-b3a4-42b0-aeb5-f4d8059018b9", "e7818b88-0a05-4884-a8e5-55d8e37090d9", "e8257439-2402-4a00-be62-ad464127301f", "e854a74a-f7dc-4b61-90a7-7c0e090a2835", "ea65e1ec-dd93-4244-a81a-c070a3256011", "ead1af14-90be-46de-a05f-cd10bbe36bd9", "a2856cd9-c37f-4a07-b295-c64e44eb4c7b" ] # 启动多线程工作 worker(idlist) delete(idlist)
相关连接:
https://zhuanlan.zhihu.com/p/336289766 ......................................................................................................Python中的并发与并行
https://www.cnblogs.com/v3ucn/p/16542155.html .........................................................................................多线程threading/多进程multiprocessing/协程asyncio