python多进程+多线程安全性能并发(模板并发最高性能可以达到1秒4000+并且不会丢失数据,电脑不同并发速度效率都不同!):
ps:之前找了特别多关于python安全取出数据库并保存的方法,但是奈何线程不安全,或者说是速度太慢!!绝大多数的文章并发线程都是不安全,速度特别慢的!
这个模板不一定是最快的,但是是比较安全的,需要有项目使用的可以直接ctrl+c,ctrl+v
需要使用的模块:
import multiprocessing
import threading
这两个模块就是目前并发中比较高级的模块!其余更高级的我也不会,哈哈!
并发不能成功的因素:
提示:在使用multiprocessing的 时候很容易会遇到一个问题,导致无法开启多进程!还有一点就是多进程开启一定要在函数入口之后,否则无法开启!!!或者是开启会弹出多个窗口,如果是写gui的话很可能会这样!
if __name__ == '__main__':
multiprocessing.freeze_support() # 在函数入口处要加上这一句代码,即可解决。
提示:还有的朋友可能会遇到,线程没运行完毕,进程就提前结束了,此类问题解决方案:
for i in multiply:#把进程对象添加到列表里面,阻塞它,还有就是在进程开启的线程里面不能使用守护线程!!
i.join()
并发的思路:
先开启多个进程,每一个进程再去启动分配任务的线程,分配任务的线程再去启动执行任务的子线程,子线程肯定是要加上全局GIL锁的,否则数据必定会不安全的。
提示:说到GIL锁,这个是一个历史原因,没有办法。具体可以看其他文章解释
概括一下GIL锁:
GIL:又叫全局解释器锁,每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程在运行,目的是解决多线程同时竞争程序中的全局变量而出现的线程安全问题。它并不是python语言的特性,仅仅是由于历史的原因在CPython解释器中难以移除,因为python语言运行环境大部分默认在CPython解释器中。Jpython就没有这个问题,但是支持模块少!!使用少!!
有了思路接下来试着写一段并发模板😁
并发模板:
提示:在安全的基础上比较快的模板,不一定是最快的,只能说高并发的话比较安全!以下的举例是数据库的并发,同样,模板可以用于并发爬虫,嘿嘿🤡就是啥都可以,这里就不演示了,io延迟可以直接到几万。
import linecache
import multiprocessing
import os
import sys
import threading
import time
import pymysql
class App_Speed:
def __init__(self, aa, min_max):
self.file1 = '数据库没有记录.txt'
self.look = threading.Lock() #这个锁是全局锁
xc_fen_pei = int((min_max[1] - min_max[0] + 1) / 5) #线程平均分配的数量
t_xc_list = []
for xc in range(5): # 线程分配_分解,这里的 5 不固定 可以自行修改
if xc == 4:
xc_min_max = (min_max[0] + xc_fen_pei * xc, min_max[1])
else:
xc_min_max = (min_max[0] + xc_fen_pei * xc, min_max[0] + (xc_fen_pei * (xc + 1)) - 1)
t = threading.Thread(target=self.xiancheng, args=(xc_min_max,)) # 分配任务线程
t_xc_list.append(t)
for tt in t_xc_list:
tt.start()
for tt_wait in t_xc_list:
tt_wait.join()
def xiancheng(self, min_max_fen_pei):
db = pymysql.connect(host='******', port=****, user='****', password='****', database='*****')
cursor = db.cursor()#这个地方可以直接改成某个接口😁
for val in range(min_max_fen_pei[0], min_max_fen_pei[1] + 1):
text_xu = linecache.getline('数据库数据.txt', val)
nei_text = text_xu.split('\n')[0]
t = threading.Thread(target=self.cha, args=(nei_text, cursor))
t.start()#执行任务的线程,这个地方自行修改 有很多方式
t.join()
def cha(self, nei_text, cursor):
self.look.acquire(blocking=True)
cursor.execute(f'''select * from table where {self.aaa} = '{nei_text}' ''')
text_cha = cursor.fetchall()
if text_cha == ():
self.file1.write(nei_text.encode() + b'\r\n')
print('无')
else:
for line21 in text_cha:
print(line21)
'''
这里是数据库成功获取值的地方!
'''
self.look.release()
if __name__ == '__main__':
multiprocessing.freeze_support()
speed = input('输入想要开启的进程数:') # 一个主进程最多开启64个子进程,否则会报错哦!
multiply = []
with open('数据库数据.txt', 'rb') as jieguo11:
count = jieguo11.read().count(b'\n') + 1 # 计算需要高并发的文件总行数,为后面的多进程分配任务
fen_pei = int(count / speed) # 每个子进程平均分配的个数
t1 = time.time()
for i in range(1, int(speed) + 1):
if i == int(speed):
shu_liang = (fen_pei * (i - 1) + 1, count) #最后一次分配的数量
else:
shu_liang = (fen_pei * (i - 1) + 1, xieru * i) # 每次不同的进程分配的数量min,max
p = multiprocessing.Process(target=App_Speed, args=(a, shu_liang)) # 多进程调用多线程
multiply.append(p)
for pp in multiply:
pp.start()
for i in multiply:
i.join(timeout=500) # 阻塞
t2 = time.time()
print("使用的时间:" + str(t2 - t1))
input() # 阻塞一下可以手动退出
sys.exit(0)
-以上就是本次分享的多进程+多线程并发哦!中间的阈值可以根据任务量调整哦!