python:多进程、多线程,,线程&进程对于操作系



线程&进程
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word
就启动了一个Word进程。进程是很多资源的集合。
有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread
)。
由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间
快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。线程是最小的执行单元,而进程由至少一个线程组成。
我们在做事情的时候,一个人做是比较慢的,如果多个人一起来做的话,就比较快了,程序也是一样的,我们想运行的速度快一点的话,就得使用多进程,或者多线程,在python里面,多线程被很多人诟病,为
什么呢,因为Python的解释器使用了GIL的一个叫全局解释器锁,它不能利用多核CPU,只能运行在一个cpu上面,但是你在运行程序的时候,看起来好像还是在一起运行的,是因为操作系统轮流让各个任务交替
执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像
所有任务都在同时执行一样。这个叫做上下文切换。
多线程:
多线程要用到threading这个模块
eg1:
import threading,time
def run(count):
time.sleep(2)
print(count)
start=time.time()
threads=[]
for i in range(5):
t=threading.Thread(target=run,args=(i,))
#创建一个线程,指定它运行哪个函数;args=(i,)是run函数的入参,一个参数要加逗号,没有参数就不写args
#如果不加线程,这段代码运行需要10秒,加了线程时间就减少很多
t.start()
threads.append(t)
#把启动的每一个线程添加到这个线程组里面

for th in threads:
th.join() #th代表的是每个子线程,join方法是等待子线程结束的意思,子线程结束了才继续往下走;
#如果没有join的话,就是主线程和子线程同时执行,子线程因为要sleep两秒,所以主线程先走完,然后子线程走完
end=time.time()
print(‘总共运行了‘,end-start)
在运行python文件时,如果你不启动多线程,那最少有一个线程在运行
线程之间是相互独立的,都是同时执行,互相没有关系
程序开始运行的时候的线程是主线程,主线程先走,并不是等其他线程走完它再走
通过多线程去调用一个函数的时候,是没有办法获取到这个函数的返回值的;如果多线程想获取返回结果,可以把返回值放添加到列表里
上面的例子,线程有6个

设置守护线程:
for i in range(5):
t=threading.Tread(target=run,args(i,))
t.setDarmon(True)
#把子线程设置成守护线程
#主线程只要一结束,子线程都得结束,有没有执行完都得结束
t.start()
print(‘over‘)


线程锁
线程锁就是,很多线程一起在操作一个数据的时候,可能会有问题,就要把这个数据加个锁,同一时间只能有一个线程操作这个数据。
from threading import Lock
num=0
lock=Lock() #申请一把锁
def run2():
global num
lock.acquire #加锁
num+=1
lock.release() #解锁
lis=[]
for i in range(5):
t=threading.Thread(target=run2)
t.start()
lis.append(t)
for t in lis:
t.join()
print(‘over‘,num)

下面来个简单的爬虫,看下多线程的效果:
import threading
import requests, time

urls = {
"baidu": ‘http://www.baidu.com‘,
"blog": ‘http://www.nnzhp.cn‘,
"besttest": ‘http://www.besttest.cn‘,
"taobao": "http://www.taobao.com",
"jd": "http://www.jd.com",
}

def run(name, url):
res = requests.get(url)
with open(name + ‘.html‘, ‘w‘, encoding=res.encoding) as fw:
fw.write(res.text)
#把网站上的html内容下载到文件里
start_time = time.time()
lis = []
for url in urls:
t = threading.Thread(target=run, args=(url, urls[url]))
t.start()
lis.append(t)
for t in lis:
t.join() #下载html内容的子线程结束之后再走这里
end_time = time.time()
print(‘run time is %s‘ % (end_time - start_time))

# 下面是单线程的执行时间
# start_time = time.time()
# for url in urls:
# run(url,urls[url])
# end_time = time.time()
# print(‘run time is %s‘%(end_time-start_time))

多进程:
python里面的多线程是利用不了多核cpu的
多进程是可以利用多核cpu的,python中多进程使用multiprocessing模块
from multiprocessing import Process
import time
def f(name):
time.sleep(2)
print(‘hello‘, name)
ps=[]
for i in range(5):
p = Process(target=f, args=(‘niu‘,))
p.start()
ps.append(p)
for p in ps:
p.join()
#多线程和多进程语法一样
#多进程适用于cpu密集型任务,即操作cpu比较多的
#多线程适用于io密集型任务,即操作input/output比较多的,比如操作磁盘

python:多进程、多线程

评论关闭