线程与进程
环境:python3.7
pip install multiprocessing -i https://pypi.douban.com/simple
pip install threading -i https://pypi.douban.com/simple
一、线程
1.1 线程的定义
线程定义:线程是进程的最小单位,一个进程至少包括一个主线程。
1.2无参数的线程
创建无参数的线程
import time
from threading import Thread
def one():
for i in range(5):
print(f'one-{i}')
time.sleep(1)
def two():
for i in range(5):
print(f'two-{i}')
time.sleep(1)
if __name__ == '__main__':
# 创建线程
t1 = Thread(target=one)
t2 = Thread(target=two)
# 执行线程
t1.start()
t2.start()
# 线程阻塞
t1.join()
t2.join()
one-0
two-0
two-1one-1
two-2one-2
two-3
one-3
two-4one-4
Process finished with exit code 0
1.3 带参数的线程
创建带参数的线程
from threading import Thread
def one(name):
print(name)
def two(name):
print(name)
if __name__ == '__main__':
# 创建线程
t1 = Thread(target=one,args=('zhangsan',))
t2 = Thread(target=two,args=('lisi',))
# 执行线程
t1.start()
t2.start()
# 线程阻塞
t1.join()
t2.join()
zhangsan
lisi
Process finished with exit code 0
1.4 守护线程
守护线程
import time
from threading import Thread
def one(name):
time.sleep(1)
print(name)
def two(name):
time.sleep(1)
print(name)
if __name__ == '__main__':
# 创建线程
t1 = Thread(target=one,args=('zhangsan',))
t2 = Thread(target=two,args=('lisi',))
#创建守护线程
t1.setDaemon(True)
t2.setDaemon(True)
# 执行线程
t1.start()
t2.start()
# 线程阻塞
t1.join()
t2.join()
lisi
zhangsan
Process finished with exit code 0
1.5 多线程之间的数据共享
多线程之间数据共享
# 多线程之间数据共享
from threading import Thread
#创建空列表用于保存添加的数据
lis = []
def one():
lis.append('one')
def two():
lis.append('two')
if __name__ == '__main__':
# 创建线程
t1 = Thread(target=one)
t2 = Thread(target=two)
# 启动线程
t1.start()
t2.start()
#阻塞线程
t1.join()
t2.join()
print(lis)
['one', 'two']
Process finished with exit code 0
1.5 线程冲突
线程冲突
from threading import Thread
num =0
def one():
global num
for i in range(1000000):
num += 1
def two():
global num
for i in range(1000000):
num += 1
if __name__ == '__main__':
# 创建线程
t1 = Thread(target=one)
t2 = Thread(target=two)
# 执行线程
t1.start()
t2.start()
# 线程阻塞
t1.join()
t2.join()
print(num)
1270450
Process finished with exit code 0
1.6 解决线程冲突
线程锁
from threading import Thread,Lock
# 实例化锁
lock = Lock()
num =0
def one():
global num
# 加锁
lock.acquire()
for i in range(1000000):
num += 1
#释放锁
lock.release()
def two():
global num
# 加锁
lock.acquire()
for i in range(1000000):
num += 1
# 释放锁
lock.release()
if __name__ == '__main__':
# 创建线程
t1 = Thread(target=one)
t2 = Thread(target=two)
# 启动线程
t1.start()
t2.start()
# 线程阻塞
t1.join()
t2.join()
print(num)
2000000
Process finished with exit code 0
二、进程
2.1 进程定义
进程的定义:执行一个程序代表一个进程
2.2 无参数的进程
import time
def run1():
for i in range(5):
print(f'run1-{i}')
time.sleep(1)
def run2():
for k in range(5):
print(f'run2-{k}')
time.sleep(1)
if __name__ == '__main__':
# 因是windows系统,只能在这里导包
from multiprocessing import Process
# 创建进程
p1 = Process(target=run1)
p2 = Process(target=run2)
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
run1-0
run2-0
run1-1
run2-1
run1-2
run2-2
run1-3
run2-3
run1-4
run2-4
Process finished with exit code 0
2.3 带参数的进程
import time
def run1(name,age=18):
print('run1-',name,age)
time.sleep(1)
def run2(name,age=19):
print('run2-',name,age)
time.sleep(2)
if __name__ == '__main__':
from multiprocessing import Process
# 创建进程
# 给进程传递非关键子参数需要定义args参数,类型是元组或者列表
# 给进程的关键字传参,需要定义kwargs参数,类型是字典
p1 = Process(target=run1,args=('a',),kwargs={'age':10})
p2 = Process(target=run2,args=('b',),kwargs={'age':11})
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
run1- a 10
run2- b 11
Process finished with exit code 0
2.4 获取进程ID
import time
import os
def run1():
# 获取子进程的编号
print('run1-',os.getpid())
time.sleep(1)
#获取主进程的进程编号
print(os.getppid())
def run2():
# 获取子进程的编号
print('run2-',os.getpid())
time.sleep(2)
# 获取主进程的进程编号
print(os.getppid())
if __name__ == '__main__':
from multiprocessing import Process
# 创建进程
p1 = Process(target=run1)
p2 = Process(target=run2)
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
run1- 5264
run2- 3068
2880
2880
Process finished with exit code 0
2.5 守护进程
import time
print('main')
def run1():
for i in range(5):
print(f'run1-{i}')
time.sleep(1)
def run2():
for k in range(5):
print(f'run2-{k}')
time.sleep(1)
if __name__ == '__main__':
from multiprocessing import Process
# 创建进程
p1 = Process(target=run1)
p2 = Process(target=run2)
# 设置为守护进程
# 当主进程执行完成后,不管子进程执行没执行完全都结束
p1.daemon = True
p2.daemon = True
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
main
main
run1-0
main
run2-0
run1-1
run2-1
run1-2
run2-2
run1-3
run2-3
run1-4
run2-4
Process finished with exit code 0
2.6 多进程之间数据不共享
l = []
def run1():
l.append('run1')
def run2():
l.append('run2')
if __name__ == '__main__':
from multiprocessing import Process
# 创建进程
p1 = Process(target=run1)
p2 = Process(target=run2)
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
print(l)
[]
Process finished with exit code 0
2.7 解决数据不共享的三种方法
2.7.1 manage方法
lis = []
def run1(lis,dic):
lis.append('run1')
dic['one']:1
def run2(lis,dic):
lis.append('run2')
dic['one']:2
if __name__ == '__main__':
from multiprocessing import Process,Manager
# manage方法
with Manager() as manager:
lis = manager.list()
dic = manager.dict()
# 创建进程
p1 = Process(target=run1,args=(lis,dic))
p2 = Process(target=run2,args=(lis,dic))
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
print(lis)
['run1', 'run2']
Process finished with exit code 0
2.7.2 Pipe方法
def run1(pi1):
pi1.send('run1')
print(pi1.recv())
def run2(pi2):
print(pi2.recv())
pi2.send('run2')
if __name__ == '__main__':
from multiprocessing import Process, Pipe
# 实例化队列
pi1,pi2 = Pipe()
# 创建进程
p1 = Process(target=run1, args=(pi1,))
p2 = Process(target=run2, args=(pi2,))
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
run1
run2
Process finished with exit code 0
2.7.3 Queue方法
import time
def run1(q):
q.put('run1')
time.sleep(1)
print(q.get())
def run2(q):
print(q.get())
q.put('run2')
if __name__ == '__main__':
from multiprocessing import Process ,Queue
# 实例化队列
q = Queue()
# 创建进程
p1 = Process(target=run1 ,args=(q,))
p2 = Process(target=run2 ,args=(q,))
# 执行进程
p1.start()
p2.start()
# 阻塞进程
p1.join()
p2.join()
run1
run2
Process finished with exit code 0
2.8 进程池
import os
import time
from multiprocessing import Pool
def run1():
print(os.getpid())
time.sleep(1)
if __name__ == '__main__':
# 创建进程池
#Pool方法的第一个参数是,初始化,多少个进程
pool = Pool(3)
for i in range(10):
pool.apply_async(run1)
# 关闭进程池
pool.close()
# 必须等待所有的请求全部执行完成之后,在结束主进程
pool.join()
2200
8324
1800
2200
8324
1800
2200
8324
1800
2200
Process finished with exit code 0