一、进程
1、multiprocessing.Process创建进程
import multiprocessing
if __name__ == '__main__':
p1 = multiprocessing.Process()
# target:表示一个可调用对象,进程启动时,调用此对象
# args:表示传递给 target 对象的参数元组
# name:当前进程的别名
p1.start()
2、使用Pool进程池创建进程
from multiprocessing import Pool
def task(i):pass
if __name__ == '__main__':
p = Pool(2)
print('----开始----')
for i in range(10):
p.apply_async(task, args=(i,))
# task可以看作是target的参数
p.close()
p.join()
3、进程间的通信
进程间的通信使用Queue来实现。
import multiprocessing
import time
def write_task(q):
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
if not q.full(): # 判断队列是否满了 满了 = True
for i in data:
msg = '消息'+str(i)
q.put(msg)
# print('写入:' + msg)
# 打印队列的大小
print('写入 %d 条数据' % q.qsize())
def read_task01(q):
time.sleep(1)
print('开始读取消息......')
while not q.empty(): # 判断列表是否为空 空 = True
print('读取:%s' % q.get(True, 2))
time.sleep(0.4)
if __name__ == '__main__':
# 创建一个队列
q = multiprocessing.Queue()
# 在创建进程时,将实例出的Queue当作参数进行传递
p_w = multiprocessing.Process(target=write_task, args=(q,))
p_r = multiprocessing.Process(target=read_task01, args=(q,))
p_w.start()
p_r.start()
p_w.join()
p_r.join()
二、线程
1、threading 创建线程
import threading
if __name__ == '__main__':
t1 = threading.Thread()
# target:表示一个可调用对象,线程启动时,调用此对象
# name:当前线程的名称
# args:表示传递给 target 对象的参数元组
# kwargs:传递给 target 对象的参数字典
# start这里真正的创建线程并启动线程
t1.start()
2、threading.Thread 创建线程
import threading
import time
# 创建一个子类MyThread子类,继承threading.Thread线程类
class MyThread(threading.Thread):
# 调用对象 start() 方法时,程序会自动调用run()方法
def run(self):
for i in range(5):
time.sleep(1)
msg = "子线程" + self.name + "执行, i = " + str(i)
print(msg)
if __name__ == '__main__':
print("----主线程开始----")
t = MyThread()
t.start()
t.join()
三、线程间的资源竞争——锁
当多个线程在操作同一个资源时有可能同时在修改一个资源或者变量,这时会对该资源造成冲突,为解决这种冲突,可以使用锁的概念,那个线程抢到资源就把锁住,然后对其进行操作,完成后再释放资源让另一个线程操作资源。这种可以解决资源的冲突问题,不过在开发时应该避免死锁(多个线程间相互等待资源释放资源,造成线程僵死状态)
import threading
'''使用互斥锁解决多线程之间的资源竞争问题'''
# 全局变量
num = 0
# 创建一把锁
mutex = threading.Lock()
def test01(temp):
print("----子线程1开始----")
global num
# 上锁
mutex.acquire()
for i in range(temp):
num += 1
# 解锁
mutex.release()
print("子线程1值:", num)
print("----子线程1结束----")
def test02(temp):
print("----子线程2开始----")
global num
# 上锁
mutex.acquire()
for i in range(temp):
num += 1
# 解锁
mutex.release()
print("子线程2值:", num)
print("----子线程2结束----")
def main():
print("----主线程开始----")
# 在线程中使用args传递函数参数,args是一个元组
t1 = threading.Thread(target=test01, args=(1000000,))
t2 = threading.Thread(target=test02, args=(1000000,))
t1.start()
t2.start()
t1.join()
t2.join()
print("主线程值:", num)
print("----主线程结束----")
if __name__ == '__main__':
main()
四、协程
在了解协程之前首先要了解Python的迭代器,生成器
1、迭代器
import time
from collections import Iterable
from collections import Iterator
class Classmate(object):
def __init__(self):
self.names = list()
self.curren_num = 0
def add(self, name):
self.names.append(name)
def __iter__(self):
'''如果想要一个对象称为一个可以迭代的对象,即可以使用for,那么必须实现__iter__方法'''
return self # 返回本类中的 __next__方法
def __next__(self):
'''成为一个可迭代器必须有的方法,__next__'''
if self.curren_num < len(self.names):
ret = self.names[self.curren_num]
self.curren_num += 1
return ret
else:
raise StopIteration
if __name__ == '__main__':
classmate = Classmate()
classmate.add("A1")
classmate.add("A2")
classmate.add("A3")
print("判断classmate是否可以迭代的对象:", isinstance(classmate, Iterable))
classmate_iterator = iter(classmate)
print("判断是classmate_iterator是否迭代器:", isinstance(classmate_iterator, Iterator))
for name in classmate:
print(name)
time.sleep(0.5)
说明白一点就是迭代器就是让一个实例出来的类对象可以使用for进行遍历,可以看到最后的for遍历的目标就是对象
2、生成器
生成器是一种特殊的迭代器
1)第一种生成器,可以看作一种列表推导式
num = (i * i for i in range(10))
print(num)
for i in num:
print(i)
2)第二种生成器
def Fibonacci(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
# 使用yield返回数据
ret = yield a
print(ret)
a, b = b, a + b
current_num += 1
# 这里的值需要在异常信息中获取(异常.value)
return "END"
if __name__ == '__main__':
# 生成器可当作类进行实例化出对象
obj = Fibonacci(10)
obj_next = Fibonacci(10)
# send方法抽取值,如果第一次使用需要传入None
print(obj.send(None))
# next方法
print(next(obj))
# send方法
print(obj.send("send方法可以传入参数")) # send方法不能向刚启动的生成器发送值
# next方法 抽取obj_next的全部值
while True:
try:
print(obj_next(obj))
except Exception as ret:
# 获得Fibonacci中return的值
print(ret.value)
break
如果说Python的列表存储的是 已经得到的数据;那么生成器存储的就是 得到数据的方法,相比之下生成器消耗的资源更少
下面使用yield来实现协程多任务的并发运行
'''使用yield实现的多任务,协程,占用资源最小'''
def task01():
while True:
print('---1---')
yield
def task02():
while True:
print('---2---')
yield
def main():
t1 = task01()
t2 = task02()
while True:
next(t1)
next(t2)
if __name__ == '__main__':
main()
使用yield实现的协程多任务,占用资源最小;可以理解为yield将本内代码暂停一小会儿,而去执行另一个代码
下面使用greenlet来实现协程
from green import greenlet
def task01():
while True:
print('---1---'
# 暂停,去执行gr2
gr2.switch()
def task02():
while True:
print('---2---')
# 暂停,去执行gr1
gr1.switch()
def main():
gr1 = greenlet(task01)
gr2 = greenlet(task02)
gr1.switch()
if __name__ == '__main__':
main()
greenlet使用代码块间的交替来实现的多任务
下面使用gevent来实现协程,这也是目前开发中常用的,推荐
import gevent
def task(n):
for i in range(n):
# print(gevent.getcurrent(), i)
print(i)
gevent.sleep(0.5)
if __name__ == '__main__':
g1 = gevent.spawn(task, 5)
g2 = gevent.spawn(task, 5)
g3 = gevent.spawn(task, 5)
g1.join()
g2.join()
g3.join()
使用gevent完成可以看作缩小版的线程
网友评论