1.什么是进程?
进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间)。比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。多进程就是“多任务”,就像使用电脑时同时打开浏览器上网、打开播放器听歌、后台还默默运行着杀毒软件一样。现代操作系统如Mac OS X,UNIX,Linux,Windows等都支持多进程,每启动一个进程,操作系统便为该进程分配一个独立的内存空间。
2.什么是线程?
线程是进程中的一个实体,是被系统独立调度和分派的基本单位。一个进程可以有一个线程,也可以有多个线程。
线程自己不拥有独立的系统资源,只拥有一点在运行中必不可少的资源,它可与同属一个进程的其它线程共享当前进程所拥有的全部资源。
一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
线程有就绪(runnable)、阻塞(blocked)和运行(running)三种基本状态以及新建(new)和死亡(dead)状态。
为什么要有多进程和多线程?
每个进程至少要干一件事,比如一个编辑器既要打字输入同时又要检测打错的拼写有时候还要区分一些关键字高亮显示,它们同属于编辑器这个进程,我们把编辑器作为一个进程,而以上这些工作就是它的子任务,如何实现他们同时工作呢?就是让每个子任务即线程短暂运行交替执行,由于它们彼此之间交替太快了,看起来就像同时运行一样。(真正的多线程需要多核CPU才能实现)
当我们要让一个python程序执行多个任务时,我们可以用多个进程或多个线程来完成我们的任务,他们之间彼此同时交替进行甚至一个任务依赖于另一个任务执行的结果,他们需要相互通信和协调,所以我们就需要用到多进程和多线程编程了。
实现多进程和多线程
1.多进程
linux下可使用os模块的fork()。
Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
import os
print('Process (%s) start...' %
os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork()
if pid == 0:
print('I am child process (%s) and my
parent is %s.' % (os.getpid(), os.getppid()))
else:
print('I (%s) just created a child process
(%s).' % (os.getpid(), pid))
windows下可以使用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.')
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个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.')
对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。
子进程
很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。
subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。
下面的例子演示了如何在Python代码中运行命令nslookup www.python.org,这和命令行直接运行的效果是一样的:
import subprocess
print('$ nslookup www.python.org')
r = subprocess.call(['nslookup',
'www.python.org'])
print('Exit code:', r)
2.多线程
使用threading模块实现多线程,Python的线程是真正的Posix Thread,而不是模拟出来的线程。
import time, threading
def loop():
print('线程%s在运行' %
threading.current_thread().name)
n = 0
while n < 5:
n = n + 1
print('线程%s >>>
%s' % (threading.current_thread().name, n))
time.sleep(1)
print('线程%s结束.' %
threading.current_thread().name)
print('线程%s在运行' %
threading.current_thread().name)
t = threading.Thread(target=loop, name='子线程1')
t2 = threading.Thread(target=loop, name='子线程2')
t.start()
t2.start()
t.join()
t2.join()
print('线程%s结束.' %
threading.current_thread().name)
或者
import time, threading
num=0
lock = threading.Lock()
def action_one():
global num
for i in range(3):
lock.acquire()
try:
print("线程1 %d"%num)
num+=1
time.sleep(1)
finally:
lock.release()
def action_two():
global num
for i in range(3):
lock.acquire()
try:
print("线程2 %d"%num)
num+=1
time.sleep(1)
finally:
lock.release()
t1 = threading.Thread(target=action_one,
ame='子线程1')
t2 = threading.Thread(target=action_two,
ame='子线程2')
t1.start()
t2.start()
t1.join()
t2.join()
学习一门python语言的前景越来越好,如果想在IT领域发展的话,可以报名合肥达内Python+人工智能课程,为您全面讲解Python课程及前景,祝您早日成为一名优选的IT行业精英,成就高薪梦想!
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!