进程&线程
# 进程&线程
# 概念
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。
有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。
# 进程
# 简单使用
from multiprocessing import Process
import os
## 子进程要执行的代码
def run_proc(name):
print('run child process %s (%s)...' % (name, os.getpid()))
if __name__ == '__main__':
print('parent process id: %s.' % os.getpid())
## args是元组,当元组一个元素是,记得加逗号,
p = Process(target=run_proc, args=('test', ))
print('child process will start.')
p.start()
## 等子进程结束再继续往下执行
p.join()
print('child process will end')
multiprocessing
模块下的Process
类(ps:首字母大写)p = Process(target=run_proc, args=('test', ))
,创建一个子进程,args
, 需要的是一个元组,元组一个元素记得要加逗号p.start()
,子进程开始p.join()
,等子进程结束再继续往下执行
# 进程池
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('task %s run %.2f seconds' % (name, end - start))
if __name__ == '__main__':
print('parent process %s.' % os.getpid())
## 限制进程池的大小,只能同时跑4个线程
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('wait for all subprocesses done...')
p.close()
## 对Pool对象调用join()方法会等待所有子进程执行完毕
## 调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了
p.join()
print('all sub process done...')
multiprocessing
模块下的Pool
类(ps:首字母大写)p = Pool(4)
,限制进程池的大小,只能同时跑4个线程p.join()
,对Pool对象调用join()
方法会等待所有子进程执行完毕,调用join()
之前必须先调用close()
,调用close()
之后就不能继续添加新的Process了
# 进程通信
进程间通信是通过
Queue
、Pipes
等实现的。
from multiprocessing import Process, Queue
import os, time, random
def write(q):
print('process to write: %s' % os.getpid())
for value in ['A', 'B', 'C']:
print('put %s to queue...' % value)
q.put(value)
time.sleep(random.random())
def read(q):
print('process to read: %s' % os.getpid())
## 这是个死循环,必须要有终止条件
while True:
value = q.get(True)
print('Get %s from queue.' % value)
if __name__ == '__main__':
## 父进程创建 queue, 并传给各个子进程
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
## 启动子进程 pr和 pw
pw.start()
pr.start()
## 等待 pw 结束
pw.join()
## pr 进程里是死循环,只能强行终止
pr.terminate()
multiprocessing
模块下的Queue
类(ps:首字母大写)pw = Process(target=write, args=(q,))
,pr = Process(target=read, args=(q,))
,创建一个读进程和写进程pr.terminate()
,pr 进程里是死循环,只能强行终止
# 线程
# 简单使用
Python的标准库提供了两个模块:
_thread
和threading
,_thread
是低级模块,threading
是高级模块,对_thread
进行了封装。绝大多数情况下,我们只需要使用threading
这个高级模块。
import time, threading
## 新线程执行的代码
def loop():
print('thread %s is running' % threading.current_thread().name)
n = 0
while n < 5:
n = n + 1
print('thread %s >>> %s' % (threading.current_thread().name, n))
time.sleep(1)
print('thread %s ended.' % threading.current_thread().name)
print('thread %s is running' % threading.current_thread().name)
## 启动线程就是把一个函数传入并创建 Thread 实例, 然后调用 start()开始执行
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print('thread %s is ended' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
, 启动线程就是把一个函数传入并创建 Thread 实例, 然后调用 start()开始执行
# 锁
import time, threading
## 假设这是存款
balance = 0
## 锁初始化
lock = threading.Lock()
def change_it(n):
## 先存后去,结果应该为0
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(2000000):
## 先获取锁
lock.acquire()
try:
## 操作
change_it(n)
finally:
## 最后记得释放锁
lock.release()
t1 = threading.Thread(target=run_thread, args=(5, ))
t2 = threading.Thread(target=run_thread, args=(8, ))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
lock = threading.Lock()
, 锁初始化lock.acquire()
, 先获取锁try: pass
,进行操作,finally: lock.release()
,释放锁
# ThreadLocal
import threading
## 全局ThreadLocal 对象
local_school = threading.local()
def process_student():
## 获取当前线程关联的student
std = local_school.student
print('hello, %s in (%s)' % (std, threading.current_thread().name))
def process_thread(name):
## 绑定ThreadLocal 的 student
local_school.student = name
process_student()
if __name__ == '__main__':
t1 = threading.Thread(target=process_thread, args=('lv',), name='Thread-1')
t2 = threading.Thread(target=process_thread, args=('wang',), name='Thread-2')
t1.start()
t2.start()
t1.join()
t2.join()
local_school = threading.local()
, 全局ThreadLocal
process_student
函数std = local_school.student
,将ThreadLocal
的student
拿出来process_thread
函数local_school.student = name
,绑定ThreadLocal
的student