线程 以及 thread类
1.多进程实现并发的socket
# server.py
import socket
from multiprocessing import Process
def chat(conn):
while True:
try:
ret = conn.recv(1024).decode('utf-8')
conn.send(ret.upper().encode('utf-8'))
except ConnectionResetError:
break
if __name__ == '__main__':
sk = socket.socket()
sk.bind(('127.0.0.1', 9000))
sk.listen()
while True:
conn,_ = sk.accept()
Process(target=chat,args=(conn,)).start()
# client.py
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
while True:
sk.send(b'hello')
msg = sk.recv(1024)
print(msg)
# 面试题
# 5个进程 p1-p5,p1,p2,结束之后p3-p5才开始,p3必须随着p4\p5结束
from multiprocessing import Process
def func():
pass
if __name__ == '__main__':
p1 = Process(target=func)
p2 = Process(target=func)
p3 = Process(target=func)
p4 = Process(target=func)
p5 = Process(target=func)
p1.start()
p2.start()
p1.join()
p2.join()
p3.daemon = True
p3.start()
p4.start()
p5.start()
p4.join()
p5.join()
2.生产者消费者模型
# 进程
# 一个进程就是一个生产者
# 一个进程就是一个消费者
# 队列
# 生产者和消费者之间的容器就是队列
import time
import random
from multiprocessing import Process,Queue
def producer(q,name,food):
for i in range(10):
time.sleep(random.random())
fd = '%s%s'%(food,i)
q.put(fd)
print('%s生产了一个%s'%(name,food))
def consumer(q,name):
while True:
food = q.get()
if not food:break
time.sleep(random.randint(1,3))
print('%s吃了%s'%(name,food))
def cp(c_count,p_count):
q = Queue(10)
for i in range(c_count):
Process(target=consumer, args=(q, 'alex')).start()
p_l = []
for i in range(p_count):
p1 = Process(target=producer, args=(q, 'wusir', '泔水'))
p1.start()
p_l.append(p1)
for p in p_l:p.join()
for i in range(c_count):
q.put(None)
if __name__ == '__main__':
cp(2,3)
3.生产者消费者实现的爬虫示例
from multiprocessing import Process,Queue
import requests
import re
import json
def producer(q,url):
response = requests.get(url)
q.put(response.text)
def consumer(q):
while True:
s = q.get()
if not s:break
com = re.compile(
'<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
'.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>', re.S)
ret = com.finditer(s)
for i in ret:
print({
"id": i.group("id"),
"title": i.group("title"),
"rating_num": i.group("rating_num"),
"comment_num": i.group("comment_num")}
)
if __name__ == '__main__':
count = 0
q = Queue(3)
p_l = []
for i in range(10):
url = 'https://movie.douban.com/top250?start=%s&filter='%count
count+=25
p = Process(target=producer,args=(q,url,)).start()
p_l.append(p)
p = Process(target=consumer, args=(q,)).start()
for p in p_l:p.join()
q.put(None)
4.joinablequeue
import time
import random
from multiprocessing import JoinableQueue,Process
def producer(q,name,food):
for i in range(10):
time.sleep(random.random())
fd = '%s%s'%(food,i)
q.put(fd)
print('%s生产了一个%s'%(name,food))
q.join()
def consumer(q,name):
while True:
food = q.get()
time.sleep(random.random())
print('%s吃了%s'%(name,food))
q.task_done()
if __name__ == '__main__':
jq = JoinableQueue()
p =Process(target=producer,args=(jq,'wusir','泔水'))
p.start()
c = Process(target=consumer,args=(jq,'alex'))
c.daemon = True
c.start()
p.join()
5.进程之间的数据共享
from multiprocessing import Manager,Process,Lock
def func(dic,lock):
with lock:
dic['count'] -= 1
if __name__ == '__main__':
# m = Manager()
with Manager() as m:
l = Lock()
dic = m.dict({'count':100})
p_l = []
for i in range(100):
p = Process(target=func,args=(dic,l))
p.start()
p_l.append(p)
for p in p_l:p.join()
print(dic)
# mulprocessing中有一个manager类
# 封装了所有和进程相关的 数据共享 数据传递
# 相关的数据类型
# 但是对于 字典 列表这一类的数据操作的时候会产生数据不安全
# 需要加锁解决问题,并且需要尽量少的使用这种方式
6.线程的理论
# 线程 开销小 数据共享 是进程的一部分
# 进程 开销大 数据隔离 是一个资源分配单位
# cpython解释器 不能实现多线程利用多核
# 锁 :GIL 全局解释器锁
# 保证了整个python程序中,只能有一个线程被CPU执行
# 原因:cpython解释器中特殊的垃圾回收机制
# GIL锁导致了线程不能并行,可以并发
# 所以使用所线程并不影响高io型的操作
# 只会对高计算型的程序由效率上的影响
# 遇到高计算 : 多进程 + 多线程
# 分布式
# cpython pypy jpython iron python
# 遇到IO操作的时候
# 5亿条cpu指令/s
# 5-6cpu指令 == 一句python代码
# 几千万条python代码
# web框架 几乎都是多线程
import os
import time
from threading import Thread
#multiprocessing 是完全仿照这threading的类写的
def func():
print('start son thread')
time.sleep(1)
print('end son thread',os.getpid())
# 启动线程 start
Thread(target=func).start()
print('start',os.getpid())
time.sleep(0.5)
print('end',os.getpid())
#开启多个子线程
def func(i):
print('start son thread',i)
time.sleep(1)
print('end son thread',i,os.getpid())
for i in range(10):
Thread(target=func,args=(i,)).start()
print('main')
#主线程什么时候结束?等待所有子线程结束之后才结束
#主线程如果结束了,主进程也就结束了
#join方法 阻塞 直到子线程执行结束
def func(i):
print('start son thread',i)
time.sleep(1)
print('end son thread',i,os.getpid())
t_l = []
for i in range(10):
t = Thread(target=func,args=(i,))
t.start()
t_l.append(t)
for t in t_l:t.join()
print('子线程执行完毕')
#使用面向对象的方式启动线程
class MyThread(Thread):
def __init__(self,i):
self.i = i
super().__init__()
def run(self):
print('start',self.i,self.ident)
time.sleep(1)
print('end',self.i)
for i in range(10):
t = MyThread(i)
t.start()
print(t.ident)
#线程里的一些其他方法
from threading import current_thread,enumerate,active_count
def func(i):
t = current_thread()
print('start son thread',i,t.ident)
time.sleep(1)
print('end son thread',i,os.getpid())
t = Thread(