概念
首先我们先了解下关于
并发与并行 的概念,这很容易让人混淆如果不注意的话,甚至会有人认为两者是一样的,统称为大家熟悉的并发编程;
Concurrent
Two queues and one coffee machine.
Parallel
Two queues and two coffee machines.
个人理解:
并发:可以理解为多个线程在单核上交替运行,每个线程都会分得一定的CPU时间片;
并行:可以理解为多个线程在多核上同时运行,每个线程都会独享一个CPU;
进程、线程、协程的区别:
- 进程:
在Python中可以理解为仅只有进程可以称为并发编程,可以充分利用多核,它不像Java和C++,因为会受制于Python的GIL(Global Interpreter Lock)全局解释器锁。
- 线程:
Python的多线程在某种程度上讲是比较尴尬的存在,受制于Python的GIL(Global Interpreter Lock)全局解释器锁,阻止Python代码同时在多个处理器核心上运行,因为一个Python解释器在同一时刻只能运行于一个处理器之中。1、对于CPU密集型计算, 并不能算真正的并行计算,不能发挥多核的作用;2、对于IO 密集型(如爬虫等),由于GIL的原因,虽然在性能上优于单线程,但多线程的切换, 资源的申请释放 成本开销同样也是不可忽略的。
- 协程:
在线程与协程之间,个人更偏向于协程,1、线程资源开销远大于协程, 线程它有自己的线程空间,在linux下可以理解为一个轻量级进程;2、线程的上下文切换可能会引起寄存器和内存间的复制拷贝等;协程在进行切换时,是代码块进行切换(栈跳转),可以更多的利用CPU时间片;
编程样例:
多进程使用
# -*- encoding:utf8 -*-
"""
author: quanbin_zhu
time : 2017/9/8 18:41
"""
import multiprocessing
#方法一:将要执行的方法作为参数传给Thread的构造方法
def work(id):
time.sleep(1)
print 'the process id is:%s' % id
for i in xrange(3):
p = multiprocessing.Process(target=work, args=(i,))
p.start()
#方法二:从Process继承,并重写run()
class WorkProcess(multiprocessing.Process):
def __init__(self, id):
multiprocessing.Process.__init__(self)
self.id = id
def run(self):
print 'the process id is:%s' % self.id
for i in xrange(3):
p = WorkProcess(i)
p.start()
多线程使用
# -*- encoding:utf8 -*-
"""
author: quanbin_zhu
time : 2017/9/8 18:46
"""
import threading
import time
#方法一:将要执行的方法作为参数传给Thread的构造方法
def show(id):
time.sleep(1)
print 'the thread id is:%s' % id
for i in xrange(3):
t =threading.Thread(target=show,args=(i,))
t.start()
#方法二:从Thread继承,并重写run()
class MyThread(threading.Thread):
def __init__(self, id):
super(MyThread, self).__init__()
self.id = id
def run(self):
time.sleep(1)
print 'the thread id is:%s' % self.id
for i in xrange(3):
t =MyThread(i)
t.start()
多协程使用
# -*- encoding:utf8 -*-
"""
author: quanbin_zhu
time : 2017/9/8 18:51
"""
import gevent
from gevent import monkey;monkey.patch_all()
from gevent.pool import Pool
from functools import partial
class Task(gevent.Greenlet):
def __init__(self, id):
super(Task, self).__init__()
self.task_id = id
def _run(self):
for index in xrange(1, 6):
print "task id %s, output value %s" % (self.task_id, index)
gevent.sleep(0)
def show(id, f, t):
for index in xrange(f, t):
print "task id %s, output value %s" % (id, index)
gevent.sleep(0)
# 方法调用
def func_dispatch():
func = partial(show, f = 1, t=3)
g1 = gevent.spawn(func, "gevent-01")
g1.join()
# 类调用
def class_dispatch():
tasks = [ Task(i) for i in xrange(0,3)]
map(lambda t: t.start(), tasks)
map(lambda t: t.join(), tasks)
# 类和Pool结合调用
def class_dispatch_with_pool():
tasks = [Task(i) for i in xrange(0, 3)]
pools = Pool(2)
map(lambda t: pools.start(t), tasks)
pools.join()
if __name__ == '__main__':
func_dispatch()