进程和程序
- 程序 :没有运行的程序,例如xxx.py这是程序,是一个静态的
- 进程 :运行起来的程序:代码 + 用到的资源
- 区别:
- 进程拥有资源,一个程序可以有几个进程
- 进程是操作i系统分配资源的基本单元
- 一个程序有多个进程是共享代码
进程的状态
工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态
- 就绪态:运行的条件都已经慢去,正在等在cpu执行
- 执行态:cpu正在执行其功能
- 等待态:等待某些条件满足,例如一个程序sleep了,此时就处于等待态
进程、线程的区别:
功能:
- 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ
- 线程,能够完成多任务,比如 一个QQ中的多个聊天窗口
定义的不同
-
进程是系统进行资源分配和调度的一个独立单位.
-
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
区别
- 一个程序至少有一个进程,一个进程至少有一个线程.
- 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
- 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
- 线线程不能够独立执行,必须依存在进程中
- 代码 ————> 进程 ————> 线程
进程间通信-Queue
说明
初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头);
-
Queue.qsize():返回当前队列包含的消息数量;
-
Queue.empty():如果队列为空,返回True,反之False ;
-
Queue.full():如果队列满了,返回True,反之False;
-
Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
-
如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;
-
如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;
-
Queue.get_nowait():相当Queue.get(False);
-
Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True;
-
-
如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;
-
如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;
- Queue.put_nowait(item):相当Queue.put(item, False);
multiprocessing.Pool常用函数解析:
- Queue.put_nowait(item):相当Queue.put(item, False);
apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
进程池
multiprocessing.Pool常用函数解析:
- apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
- lose():关闭Pool,使其不再接受新的任务;
- terminate():不管任务是否完成,立即终止;
- join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
进程池中的Queue:
如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue(),否则会得到一条如下的错误信息:
RuntimeError: Queue objects should only be shared between processes through inheritance
示例代码
01_使用“进程”实现多任务
import multiprocessing
import time
def test1():
while True:
print("-----1-----")
time.sleep(1)
def test2():
while True:
print("-----2-----")
time.sleep(1)
def main():
p1 = multiprocessing.Process(target=test1)
p2 = multiprocessing.Process(target=test2)
p1.start()
p2.start()
if __name__ == '__main__':
main()
02_Queue实现多进程数据共享
import multiprocessing
import time
def download_data(q):
"""模拟下载数据"""
data = [11, 22, 33, 44]
# 向队列里写数据
for temp in data:
q.put(temp)
# time.sleep(1)
print("----下载器数据已经下载完成并存入队列里----")
def analysis_data(q):
"""模拟数据处理"""
read_data = list()
# 从队列中读取数据
while True:
data = q.get()
read_data.append(data)
# 模拟数据处理
print(read_data)
if q.empty():
break
def main():
q = multiprocessing.Queue()
p1 = multiprocessing.Process(target=download_data,args=(q,))
p2 = multiprocessing.Process(target=analysis_data,args=(q,))
p1.start()
p2.start()
if __name__ == '__main__':
main()
运行结果:
----下载器数据已经下载完成并存入队列里----
[11]
[11, 22]
[11, 22, 33]
[11, 22, 33, 44]
[Finished in 0.6s]
03_进程池
from multiprocessing import Pool
import os, time, random
def worker(msg):
t_start = time.time()
print("%s开始执行,进程号为%d" % (msg,os.getpid()))
time.sleep(random.random()*2)
t_stop = time.time()
print(msg,"执行完毕,耗时%0.2f" % (t_stop-t_start))
po = Pool(3)
for i in range(0,10):
po.apply_async(worker,(i,))
print("-------start-------")
po.close()
po.join()
print("--------end--------")
运行结果: