多任务处理可以为多进程或者多线程,一个进程中至少有一个线程。
以下代码与例子均来自廖雪峰的python教程。
在windows下通过multiprocessing中的Process类生成一个进程。
from multiprocessing import Process
import os
def run_func(name):
print('my process name is %s and process id is %s'%(name, os.getpid()))
if __name__ == '__main__':
print('parent process id is %s'%os.getpid())
p = Process(target=run_func, args=('mashijia',))
print('child process will start')
p.start()
p.join()
print('child process end')
运行结果为。
parent process id is 3312
child process will start
my process name is mashijia and process id is 4700
child process end
进程pool的使用方法。
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('run task name:%s, process id is %s'%(name, os.getpid()))
start = time.time()
time.sleep(random.random()*3)
end = time.time()
print('task %s run time is %0.2f'%(name, (end-start)))
if __name__ == '__main__':
print('parent process id is %s'%os.getpid())
start = time.time()
p = Pool(5)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('waiting all subprocess done')
p.close()
p.join()
end = time.time()
print('all subprocess done in %0.3f seconds'%(end-start))
运行结果。
parent process id is 5164
waiting all subprocess done
run task name:0, process id is 4216
run task name:1, process id is 5788
run task name:2, process id is 3668
run task name:3, process id is 5972
run task name:4, process id is 5616
task 3 run time is 0.19
task 2 run time is 0.30
task 0 run time is 1.52
task 1 run time is 2.30
task 4 run time is 2.35
all subprocess done in 2.732 seconds
通过multiprocessing模块中Queue类实现两个进程之间的通信,可以一个进程监听数据,得到数据后就推送到queue,一个进程处理数据,只要queue中有数据就处理,没有数据就处于死循环状态。
from multiprocessing import Process, Queue
import os, time, random
def write(queue):
print('process id %s for writing'%os.getpid())
for value in range(4):
print('put %s into queque'%value)
queue.put(value)
time.sleep(random.random()*3)
def read(queue):
print('process id %s for reading'%os.getpid())
while True:
value = queue.get()
print('get value is %s'%value)
if __name__ == '__main__':
queue = Queue()
pw = Process(target=write, args=(queue,))
pr = Process(target=read, args=(queue,))
pw.start()
pr.start()
pw.join()
pr.terminate()
运行结果。
process id 5632 for writing
put 0 into queque
process id 5008 for reading
get value is 0
put 1 into queque
get value is 1
put 2 into queque
get value is 2
put 3 into queque
get value is 3
多线程处理使用python库中的threading模块。
import time, threading
def loop():
print('thread %s is running'%threading.current_thread().name)
for i in range(1,6):
print('thread name is %s and loop num is %s'%(threading.current_thread().name, i))
time.sleep(2)
print('thread %s is ended'%threading.current_thread().name)
if __name__ == '__main__':
print('thread %s is running'%threading.current_thread().name)
thread = threading.Thread(target=loop, name='loop_thread')
thread.start()
thread.join()
print('thread %s is ended'%threading.current_thread().name)
运行结果。
thread MainThread is running
thread loop_thread is running
thread name is loop_thread and loop num is 1
thread name is loop_thread and loop num is 2
thread name is loop_thread and loop num is 3
thread name is loop_thread and loop num is 4
thread name is loop_thread and loop num is 5
thread loop_thread is ended
thread MainThread is ended
如果多个线程对同一个变量同时操作,不加lock会出现错误结果。
import time, threading
balance = 0
def change_it(n):
global balance#声明该变量在外部定义并且是全局变量
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(100000):
change_it(n)
if __name__ == '__main__':
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(10,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
运行结果。
是因为balance = balance+n是分为两部执行的,先将balance+n赋值给临时变量,再将临时变量赋值给balance。存在第一个线程已经运行完一个加减操作了,接下来就遇到第二个线程将临时变量赋值给balance,这样就会出现错误了。
通过加thread.lock()将一个完整操作加锁,加锁后只能有一个线程操作,只有当锁释放了,其他线程才能有机会执行。
lock = threading.Lock()
def run_thread(n):
for i in range(100000):
lock.acquire()
try:
change_it(n)
finally:
lock.release()