本文学习自廖雪峰的官方网站和菜鸟教程。
进程和线程
对于操作系统来说,一个任务就是一个进程(Process)。
一个进程可以有多个线程(Thread)。
多任务的实现有3种方式:
多进程模式;
多线程模式;
多进程+多线程模式。
第三种太复杂,实际很少用。
实际上进程和线程实现多任务比较复杂,涉及他们之间执行的顺序,数据的传递等。
直接学multiprocessing吧。
multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:
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 %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')
结果:
Parent process 5192.
Child process will start.
Run child process test (5592)...
Child process end.
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process
实例,用start()
方法启动。join()
方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
Pool
如果要启动大量的子进程,可以用进程池的方式批量创建子进程:
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 runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
结果:
Parent process 228.
Waiting for all subprocesses done...
Run task 0 (8868)...
Run task 1 (15848)...
Run task 2 (11312)...
Run task 3 (13488)...
Task 3 runs 0.03 seconds.
Run task 4 (13488)...
Task 4 runs 1.24 seconds.
Task 0 runs 1.71 seconds.
Task 1 runs 2.31 seconds.
Task 2 runs 2.35 seconds.
All subprocesses done.
对Pool对象调用join()
方法会等待所有子进程执行完毕,调用join()
之前必须先调用close()
,调用close()
之后就不能继续添加新的Process了。
调用join()
就是阻塞主进程,等待紫禁城执行完再继续执行,如果不加close,join这两句,就会先把主进程执行完,先打印All subprocesses done.然后才会显示各个子进程的运行时间
以上说的都是进程!!进程!!
下面说的才是线程!!线程!!
使用threading
模块,启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行:
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。
所以使用时需要上锁,具体的就不学了,估计不得不用的时候才会用。
具体进程还是线程,用哪个,我就不复制粘贴了,等到以后有了感受再来写,贴一个链接防止找不到。