1,进程和线程的区别
打开一个程序相当于一个进程,而程序中的读取数据,传输数据等不同的功能相当于不同的线程。线程没有利用到多核的优势,一个进程内的所有线程的内存是共享的,但是开启线程不会消耗太大的资源;进程中的内存都是独立的,每次开启一个进程都需要申请新的内存空间。
2,开启进程(线程)的两种方法
进程:
#使用方法来来使用多进程 import time import random from multiprocessing import Process def piao(name): print('%s piaoing' %name) time.sleep(random.randrange(1,5)) print('%s piao end' %name) if __name__ == '__main__': #实例化得到四个对象 p1=Process(target=piao,args=('egon',)) #必须加,号 p2=Process(target=piao,args=('alex',)) p3=Process(target=piao,args=('wupeqi',)) p4=Process(target=piao,args=('yuanhao',)) #调用对象下的方法,开启四个进程 p1.start() p2.start() p3.start() p4.start() print('主')
#使用类来使用多进程
import time
import random
from multiprocessing import Process
class Piao(Process):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print('%s piaoing' %self.name)
time.sleep(random.randrange(1,5))
print('%s piao end' %self.name)
if __name__ == '__main__':
#实例化得到四个对象
p1=Piao('egon')
p2=Piao('alex')
p3=Piao('wupeiqi')
p4=Piao('yuanhao')
#调用对象下的方法,开启四个进程
p1.start() #start会自动调用run
p2.start()
p3.start()
p4.start()
print('主')
线程
因为GIL的存在,所以在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
#线程中使用方法来使用多线程
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name)
if __name__ == '__main__':
t=Thread(target=sayhi,args=('egon',))
t.start()
print('主线程')
#线程中使用类来使用多线程 from threading import Thread import time class Sayhi(Thread): def __init__(self,name): super().__init__() self.name=name def run(self): time.sleep(2) print('%s say hello' % self.name) if __name__ == '__main__': t = Sayhi('egon') t.start() print('主线程')
3,进程池和线程池
#进程池使用pool.apply
加入进程池是并行的,没有并行的效果
from multiprocessing import Process, Pool
# 从multiprocessing导入pool
import time, os
def Foo(i):
time.sleep(2)
print("in process", os.getpid()) # 打印进程id
return i + 100
def Bar(arg):
print('-->exec done:', arg)
if __name__ == '__main__': ##这行代码用途是如果主动执行该代码的.py文件,则该代码下面的代码可以被执行;如果该.py模块被导入到其他模块中,从其他模块执行该.py模块,则该行下面的代码不会被执行。 有些时候可以用这种方式用于测试,在该行代码下面写一些测试代码。。
pool = Pool(5) # 同时只能放入5个进程
for i in range(10): # 创建10个进程,但是因为pool的限制,只有放入进程池中的5个进程才会被执行(),其他的被挂起了,如果进程池中其中有两个进程执行完了,就会补进2个进程进去。
# pool.apply_async(func=Foo, args=(i,), callback=Bar)
pool.apply(func=Foo, args=(i,)) # pool.apply用来将进程放入pool
print('end') # 执行完毕
pool.close() # 允许pool中的进程关闭(close必须在join前面,可以理解close相当于一个开关吧)
pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
#pool.apply_async 加入进程池的方式是并行
from multiprocessing import Process, Pool import time, os
def Foo(i): time.sleep(2) print("in process", os.getpid()) return i + 100 def Bar(arg): print('-->exec done:', arg) if __name__ == '__main__': pool = Pool(5) for i in range(10): pool.apply_async(func=Foo, args=(i,)) ## 使用pool.apply_async就可以并行了 print('end') pool.close() pool.join()
#并行运行并且使用回调函数 from multiprocessing import Process, Pool import time, os def Foo(i): time.sleep(2) print("in process", os.getpid()) return i + 100 def Bar(arg): print('-->exec done:', arg, os.getpid()) if __name__ == '__main__': pool = Pool(5) print("主进程:", os.getpid()) # 打印主进程id for i in range(10): pool.apply_async(func=Foo, args=(i,), callback=Bar) ##callback叫做回调,就是当执行完了func=Foo后,才会执行callback=Bar(每个进程执行完了后都会执行回调)。 ## 回调可以用于当执行完代码后做一些后续操作,比如查看完命令后,通过回调进行备份;或者执行完什么动作后,做个日志等。 ## 备份、写日志等在子进程中也可以执行,但是为什么要用回调呢! 这是因为如果用子进程,有10个子进程就得连接数据库十次,而使用回调的话是用主进程连接数据库,所以只连接一次就可以了,这样写能大大提高运行效率。 ##通过主进程建立数据库的连接的话,因为在同一个进程中只能在数据库建立一次连接,所以即使是多次被子进程回调,也不会重复建立连接的,因为数据库会限制同一个进程最大连接数,这都是有数据库设置的。 print('end') pool.close() pool.join()
4、协程
线程和协程的区别:线程的切换时操作系统执行的,分两种情况1是该任务发生了阻塞,任务运行时间到了或者一个优先级更高的任务代替了它。
而协程是用户程序自己控制调度的。
from datetime import datetime import asyncio async def add(n): print(datetime.now().strftime('%H:%M:%S.%f')) count = 0 for i in range(n): count += i print(datetime.now().strftime('%H:%M:%S.%f')) return count async def fun(n): res = await add(n) print(f'res = {res}') loop = asyncio.get_event_loop() tasks = [fun(20000000), fun(30000000)] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
import time import queue def consumer(name): print("--->starting eating baozi...") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name, new_baozi)) # time.sleep(5) def producer(): r = con.__next__() r = con2.__next__() n = 0 while n < 5: n += 1 con.send(n) con2.send(n) print("\033[32;1m[producer]\033[0m is making baozi %s" % n) if __name__ == '__main__': con = consumer("c1") con2 = consumer("c2") p = producer()
import gevent def eat(name): print('%s eat 1' %name) gevent.sleep(2) print('%s eat 2' %name) def play(name): print('%s play 1' %name) gevent.sleep(1) print('%s play 2' %name) g1=gevent.spawn(eat,'egon') g2=gevent.spawn(play,name='egon') g1.join() g2.join() #或者gevent.joinall([g1,g2]) print('主')
人生苦短,我用cnblog