程序
-Program,一系列指令的集合
-使用编程语言所编写的指令的集合,用于实现一定的功能
进程
-启动后的程序在系统中就有一个进程,系统会为这个进程分配内存空间
os.fork()函数
-只适用于Unix、Linux、Mac操作系统
multiprocessing模块
-Process(group=None,target,name,args,kwargs)
Pool进程池
import time
from multiprocessing import Process
import os
def tast():
print(f'我是子进程,我的PID是:{os.getpid()},我的父进程是:{os.getppid()}')
time.sleep(3)
if __name__ == '__main__':
start = time.time() #开始时间
lst = []
print('主进程开始执行:')
#创建5个子进程
for i in range(5):
#创建1个子进程对象
pro = Process(target=tast)
#启动进程
pro.start()
#启动的进程添加到列表中
lst.append(pro)
#列表中的每个成员都是一个进程 将子进程加入列表,运行时间变快
for item in lst:
item.join() #阻塞主进程
print(f'运行5个子进程一共花了多长时间:{time.time()-start}')
print('主进程执行结束') #只是主进程中没有代码了,但并不是主进程结束
#主进程要等到所有的子进程结束之后才会结束
import os
import time
from multiprocessing import Process
def sub_process1(name):
print(f'子进程PID:{os.getpid()},父进程的PID:{os.getppid()},---------------------{name}')
time.sleep(1)
def sub_process2(age):
print(f'子进程PID:{os.getpid()},父进程的PID:{os.getppid()},---------------------{age}')
time.sleep(1)
if __name__ == '__main__':
print('父进程开始执行')
for i in range(5):
#创建子进程1
p1 = Process(target=sub_process1,args=('jww',))
#创建子进程2
p2 = Process(target=sub_process2,args=(18,))
#启动子进程
p1.start()
p2.start()
# print(p1.name, '是否执行完毕', p1.is_alive())
# print(p2.name, '是否执行完毕', p2.is_alive())
# print(p1.name, '的PID:', p1.pid)
# print(p2.name, '的PID:', p2.pid)
p1.join() #父进程等待p1执行结束
p2.join() #父进程等待p2执行结束
print('父进程执行结束')
#多个进程之间同时执行的顺序是随机的,不会根据创建的顺序执行
import os
import time
from multiprocessing import Process
def sub_process1(name):
print(f'子进程PID:{os.getpid()},父进程的PID:{os.getppid()},---------------------{name}')
time.sleep(1)
def sub_process2(age):
print(f'子进程PID:{os.getpid()},父进程的PID:{os.getppid()},---------------------{age}')
time.sleep(1)
if __name__ == '__main__':
print('父进程开始执行')
for i in range(5):
# p1 = Process() #没有给定target参数,默认调用run方法
# p2 = Process()
# p1.start() #自动调用run方法执行
# p2.start()
# p1.run()
# p2.run()
p1 = Process(target=sub_process1,args=('jww',))
p2 = Process(target=sub_process2,args=(18,))
p1.start()
p2.start()
#终止进程
p1.terminate()
p2.terminate()
print('父进程执行结束')
import os
from multiprocessing import Process
#自定义类
class SubProcess(Process):
#初始化的方法
def __init__(self,name):
#调用父类Process的初始化方法
Process.__init__(self)
self.name = name
#重写run方法
def run(self):
print(f'子进程的名称:{self.name},PID:{os.getpid()},父进程的PID:{os.getppid()}')
if __name__ == '__main__':
print('父进程开始执行')
lst = []
for i in range(1,6):
p1 = SubProcess(f'进程--{i}')
#启动进程
p1.start()
lst.append(p1)
for item in lst:
item.join()
print('父进程执行结束')
from multiprocessing import Pool
import time
import os
#编写任务
def task(name):
print(f'子进程的PID:{os.getpid()},执行任务---task{name}')
time.sleep(1)
if __name__ == '__main__':
start = time.time()
print('父进程开始执行')
#创建一个进程池
p = Pool(3) #进程池里,最大进程的个数
#创建10个进程
for i in range(10):
#以非阻塞方式进行
# p.apply_async(func=task,args=(i,)) #穿插交替进行
#以阻塞方式进行
p.apply(func=task,args=(i,))
p.close() #关闭进程,不再接收新任务
p.join() #阻塞父进程,等待子进程结束
print('所有子进程结束,父进程执行结束')
print(time.time()-start)
多个进程间的数据可以共享吗?——不可以
全局变量a在父进程和两个子进程中各一份,各自操作各自a的值,对于a的计算结果并没有在进程之间传递,进程之间并没有共享数据
from multiprocessing import Process
a = 100
def add():
print('子进程1开始执行')
global a
a += 30
print('a =',a)
print('子进程1执行结束')
def sub():
print('子进程2开始执行')
global a
a -= 50
print('a =',a)
print('子进程2执行结束')
if __name__ == '__main__':
print('父进程开始执行')
print('a的值为:',a)
#创建加的进程
p1 = Process(target=add)
p2 = Process(target=sub)
#启动两个子进程
p1.start()
p2.start()
#等待p1进程执行结束
p1.join()
#等待p2进程执行结束
p2.join()
print('父进程执行结束')
from multiprocessing import Queue
if __name__ == '__main__':
#创建一个队列,最多可以接收3条消息
q = Queue(3)
print('队列是否为空:',q.empty())
print('队列是否为满:',q.full())
#向队列中添加消息
q.put('hello') #block默认为True
q.put('world')
print('队列是否为空:', q.empty())
print('队列是否为满:', q.full())
q.put('python')
print('队列是否为满:', q.full())
print('队列中消息的个数:',q.qsize())
# q.put('html') #队列已满,block=True默认为True,一直等待队列有空位置才会将html入队,然后继续执行
# q.put('html',block=True,timeout=2) #等待2秒,若还没有空位置,抛出异常queue.Full
# q.put_nowait('html') #相当于q.put('html',block=False),不等待,queue.Full
print('-------------------------------------')
#从队列中获取消息 出队的操作
print(q.get())
print('出队之后,消息的个数:',q.qsize())
q.put_nowait('html') #入队
print('入队之后,消息的个数:',q.qsize())
#通过遍历出队所有元素
if not q.empty():
for i in range(q.qsize()):
print(q.get_nowait())
print('队列是否为空:', q.empty())
print('队列是否为满:', q.full())
print('队列中消息的个数:', q.qsize())
from multiprocessing import Process, Queue
import time
a = 100
#向队列中写入消息的进程要执行的函数
def write_msg(q):
global a
if not q.full():
for i in range(1,6):
a -= 10
q.put(a) #入队操作,将a的值进行入队
print('a入队时的值:',a)
#从队列中读取消息的进程要执行的函数
def read_msg(q):
time.sleep(1)
while not q.empty():
print('出队a的值:',q.get())
if __name__ == '__main__':
print('父进程开始执行')
q = Queue() #由父进程创建队列,传给子进程,没有写个数,说明队列可接收的消息个数没有上限
#创建两个子进程
p1 = Process(target=write_msg,args=(q,))
p2 = Process(target=read_msg,args=(q,))
#启动两个子进程
p1.start()
p2.start()
#等待写书进程结束
p1.join()
p2.join()
print('----------------父进程执行结束------------------')
1. 函数方式创建线程
#多线程
import threading
from threading import Thread
import time
#编写函数
def tast():
for i in range(3):
time.sleep(1)
print(f'线程{threading.current_thread().name}正在执行,{i}')
if __name__ == '__main__':
print('主线程开始执行')
start = time.time()
# for i in range(2):
# t = Thread(target=tast)
# #启动线程
# t.start()
# t.join()
lst = [Thread(target=tast) for i in range(2)] #放入列表,再启动,再join,可以提高程序运行效率
for item in lst:
item.start()
for item in lst:
item.join()
print(f'共耗时{time.time()-start}')
#多个线程执行是无序的,每次执行结果都不同
2. 继承方式创建线程
import threading
from threading import Thread
import time
class SubThread(Thread):
def run(self):
for i in range(3):
time.sleep(1)
print(f'线程{threading.current_thread().name}正在执行,i的值为{i}')
if __name__ == '__main__':
print('主线程开始执行')
lst = [SubThread() for i in range(2)] #创建两个线程,放到列表中存储
for item in lst:
item.start()
for item in lst:
item.join()
print('主线程执行结束')
from threading import Thread
import time
a = 100
def add():
print('加的线程开始执行')
global a
a += 30
print(f'a的值为:{a}')
print('加的线程结束')
def sub():
print('减的线程开始执行')
global a
a -= 50
print(f'a的值为:{a}')
print('减的线程结束')
if __name__ == '__main__':
print('主线程开始执行')
print(f'------全局变量a的值{a}------')
add = Thread(target=add)
sub = Thread(target=sub)
#启动线程
add.start()
sub.start()
add.join() #等待加的线程结束
sub.join() #等待减的线程结束
print('---------主线程结束---------')
-多线程都是在同一个进程中运行的,因此在进程中的全局变量所有线程都可以共享,这就造成了一个问题,因为线程的顺序是无序的,有可能会造成数据错乱
出现了几个线程卖同一张票的情况
import threading
from threading import Thread
import time
ticket = 50
def sale_ticket():
global ticket
for i in range(1000):
if ticket>0:
print(threading.current_thread().name + f'正在出售第{ticket}张票')
ticket -= 1
time.sleep(1)
if __name__ == '__main__':
for i in range(3):
t = Thread(target=sale_ticket)
t.start()
-互斥锁的两种状态:锁定和非锁定
-当线程访问共享资源时,先将其“锁定“,其他线程不能修改;直到该线程释放资源时,将资源的状态变成”非锁定“时,其他线程才能操作共享资源
解决方法
import threading
from threading import Thread,Lock
import time
ticket = 50
lock_obj = Lock() #创建锁对象
def sale_ticket():
global ticket
for i in range(1000):
lock_obj.acquire() # 加锁
if ticket>0:
print(threading.current_thread().name + f'正在出售第{ticket}张票')
ticket -= 1
time.sleep(1)
lock_obj.release() #释放锁
if __name__ == '__main__':
for i in range(3):
t = Thread(target=sale_ticket)
t.start()
带来的新问题:程序运行效率变低
from queue import Queue #实现线程之间的通信
# from multiprocessing import Queue
from threading import Thread
import time
#创建一个生产者类
class Producer(Thread):
def __init__(self,name,queue):
Thread.__init__(self,name=name)
self.queue = queue
def run(self):
for i in range(1,6):
print(f'{self.name}将产品{i}放入队列')
self.queue.put(i)
time.sleep(1)
print('-----------生产者线程完成了所有数据的存放-----------')
#创建一个消费者类
class Consumer(Thread):
def __init__(self,name,queue):
Thread.__init__(self,name=name)
self.queue = queue
def run(self):
for _ in range(5):
value = self.queue.get()
print(f'消费者线程{self.name}取出了{value}')
time.sleep(1)
print('-----------消费者线程完成了所有数据的取出-----------')
if __name__ == '__main__':
#创建队列
queue = Queue()
#创建生产者线程
p = Producer('Produce',queue)
#创建消费者线程
con = Consumer('Consumer',queue)
#启动线程
p.start()
con.start()
#等待生产者线程结束,等待消费者线程结束
p.join()
con.join()
print('主线程运行结束')