如何查看进程id号
进程都有几个属性:进程名、进程id号(pid-->process id)
每一个进程都有一个唯一的id号, 通过这个id号就能找到这个进程
import os
import time
def task():
print("task中的子进程号:", os.getpid())
print("主进程中的进程号:", os.getppid()) # parent
time.sleep(20)
from multiprocessing import Process
if __name__ == '__main__':
p = Process(target=task, )
p.start()
# 如何查看p进程的进程号
print("子进程的进程号:", p.pid) # 217164
# 如何查看主进程的进程号:
print("主进程的进程号:", os.getpid()) # os.getgid()这一句代码写在哪个进程下,输出的就是这个进程的进程号
time.sleep(10)
队列的使用(queue)
常见的数据结构:链表、单链表、双链表、循环链表、栈、队列、树、二叉树、平衡二叉树、红黑树、b树、b+树、b-树,图等
队列:先进先出
# 怎么样能够得到一个队列呢?
在python中,内置的有一个类,Queue
from multiprocessing import Queue
if __name__ == '__main__':
q = Queue(3) # 队列的大小默认很大
# 1. 如何入队、
"""obj, block=True, timeout=None"""
q.put('hellowrold1')
q.put('helloworld2')
q.put('helloworld3')
# q.put('helloworld4', block=False) # 如果你知道了block参数,当队列满的时候,放不进去的时候,直接报错
# q.put('helloworld4', timeout=3) # 如果你知道了timeout参数,当往队列中放入数据的时候,等待3秒,如果放不进去,直接报错
# q.put_nowait('helloworld4') # 往队列中放入数据的时候,放不进去直接报错, 指定了参数:block=False
# 2. 出队
# print(q.get())
# print(q.get())
print(q.get())
""" block=True, timeout=None"""
# print(q.get(block=False))
# print(q.get(timeout=3))
# q.get_nowait() #
# print(q.qsize()) # 队列中剩余的数据量, 这个方法的结果有点不准确.
# print(q.empty())
# print(q.full())
解决进程之间的数据隔离问题
def task(q):
a = 1
q.put("子进程写入的数据111")
q.put(a)
from multiprocessing import Process,Queue
if __name__ == '__main__':
q = Queue(3)
p = Process(target=task,args=(q, ) )
p.start()
"""
我在子进程中放入一个数据,然后在主进程中取出这个数据,如果能去得到,就说明通信了,如果取不到就说明不通信
"""
# 在主进程中取出子进程写进去的数据
print(q.get())
print(q.get())
现在队列中的数据在哪里存着? 在内存中存着,当数据量很大的时候,很占用我们机器的内存
以后我们可能会使用专业的消息队列: kafka、rabbitmq、rocketmq等专业的消息队列
当前使用较多的消息队列有:RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等
生产者消费者模型
它不是只存在于Python中,在其他语言中也是有的,甚至于他跟语言就没有关系
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题,该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
版本4: 多生产者 少消费者的情况
def producer(q, name, food):
"""让生产者生产10个包子"""
for i in range(10):
"""生产的包子放在哪里? 队列里"""
q.put("生产者:%s,生产了第%s个 %s" % (name, i, food))
import time
time.sleep(0.1)
def consumer(q):
while True:
res = q.get()
# if q.empty():
# break
if res is None:
break
print(res)
from multiprocessing import Process, Queue
if __name__ == '__main__':
q = Queue(20)
# 4个生产者
p1 = Process(target=producer, args=(q, 'kevin', '包子'))
p2 = Process(target=producer, args=(q, 'jason', '豆浆'))
p3 = Process(target=producer, args=(q, 'tank', '面包'))
p4 = Process(target=producer, args=(q, 'oscar', '豆汁'))
p1.start()
p2.start()
p3.start()
p4.start()
# 两个消费者
p5 = Process(target=consumer, args=(q,))
p6 = Process(target=consumer, args=(q,))
p5.start()
p6.start()
p1.join()
p2.join()
p3.join()
p4.join()
"""放的None的数量超过消费者的数量就可以正常结束程序"""
q.put(None)
q.put(None)
队列可能会出现什么问题,如何解决的?
队列积压问题,队列里面的数据不能够被及时的消费掉造成的问题
把队列中的数据消费掉,以后我们会有专业的队列工具,是一个网站,手动的处理
线程理论
进程是一个任务的执行过程,在这个过程中实际做事的是线程,线程是开在进程里面的,需要先有进程,在有线程,一个进程中至少有一个线程,当然,也可以有多个线程。
进程是资源分配的基本单位,线程是CPU执行的最小单位
进程和线程都是有操作系统来调度的,协程它是有程序员来调度的。
进程 >>> 线程 >>> 协程
资源消耗是最多的 >>> 线程的资源 >>> 协程的
我们学了进程和线程之后,以后到底是开多进程还是开多线程呢? """ GIL锁相关
如何开启线程
def task():
print("task执行了") # task执行了
from multiprocessing import Process
from threading import Thread
if __name__ == '__main__':
t = Thread(target=task)
t.start()
from multiprocessing import Process
from threading import Thread
import threading
if __name__ == '__main__':
"""
target=None, name=None,
args=(), kwargs=None, *, daemon=None
name='ly_1': 修改线程名称
"""
t = Thread(target=task, name='ly_1', args=('kevin', 'jason' ), kwargs={'age':18})
# t.daemon = True
# t.setDaemon(True) # 守护线程:主线程结束,子线程跟着结束
t.start()
# print(t.name) # Thread-1
# print(123)
#####几个方法
# print(t.isAlive())
# print(t.is_alive())
# print(t.getName())
# print(t.name)
# t.setName('ly_2')
# print(t.getName())
print(threading.currentThread()) # <_MainThread(MainThread, started 110848)>
如何开启多线程
def task(i):
print(i)
from threading import Thread
if __name__ == '__main__':
tt = []
for i in range(5):
t = Thread(target=task, args=(i, ))
t.start()
tt.append(t)
for j in tt:
j.join()
print("123")
进程和线程的比较
1. 进程的开销远远大于线程的开销
2. 进程之间的数据是隔离的,线程之间的数据呢? 线程之间的数据是共享的,严格的来说:同一个进程下的线程之间的数据是共享的
3. 想让不同进程之间的线程之间的数据共享------->还是让进程之间通信------->线程之间也通信了--->队列