python 多线程, 多进程, 协程
1. 介绍:
threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。python当前版本的多线程库没有实现优先级、线程组,线程也不能被停止、暂停、恢复、中断。
2. 1 线程执行函数
#!/bin/python #coding:utf8 import threading import time def action(arg): time.sleep(1) print "this ia arg %s \n" % arg thread_list = [] for i in xrange(4): t = threading.Thread(target=action,args=(i,)) t.start() thread_list.append(t) for t in thread_list: t.join() print 'main end'
# coding:utf-8 import threading import time gl_num = 0 lock = threading.RLock() # 调用acquire([timeout])时,线程将一直阻塞, # 直到获得锁定或者直到timeout秒后(timeout参数可选)。 # 返回是否获得锁。 def Func(): lock.acquire() global gl_num gl_num += 1 time.sleep(1) print gl_num lock.release() for i in range(10): t = threading.Thread(target=Func) t.start()
在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)
2.2 线程继承类
import threading import time class MyThread(threading.Thread): def __init__(self,arg): super(MyThread,self).__init__() self.arg = arg def run(self): time.sleep(1) print 'this arg is %s \n' % self.arg thread_list = [] for i in xrange(4): t = MyThread(i) t.setDaemon(True) t.start() thread_list.append(t) for i in thread_list: t.join() print 'main end'
3.介绍:
构造方法:
Thread(group=None, target=None, name=None, args=(), kwargs={})
group: 线程组,目前还没有实现,库引用中提示必须是None;
target: 要执行的方法;
name: 线程名;
args/kwargs: 要传入方法的参数。
实例方法:
isAlive(): 返回线程是否在运行。正在运行指启动后、终止前。
get/setName(name): 获取/设置线程名。
start(): 线程准备就绪,等待CPU调度
is/setDaemon(bool): 获取/设置是后台线程(默认前台线程(False))。(在start之前设置)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止
如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
start(): 启动线程。
join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。
join()阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout,即使设置了setDeamon(True)主线程依然要等待子线程结束。
二、多进程
multiprocessing
python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
1.1 函数
import multiprocessing import time def worker(interval): n = 5 while n > 0: print "this is n=%d" % n time.sleep(interval) n -=1 p = multiprocessing.Process(target=worker,args=(3,)) m = multiprocessing.Process(target=worker,args=(4,)) p.start() m.start() print m.pid print '-----------' print p.pid print p.name print p.is_alive() print multiprocessing.active_children() # 获取所有的进程 print 'main end'
1.2 类
import multiprocessing import time class ClockProcess(multiprocessing.Process): def __init__(self, interval): multiprocessing.Process.__init__(self) self.interval = interval def run(self): n = 5 while n > 0: print("the time is {0}".format(time.ctime())) time.sleep(self.interval) n -= 1 if __name__ == '__main__': p = ClockProcess(3) p.start()
p.daemon = True
因子进程设置了daemon属性,主进程结束,它们就随着结束了,# 默认是false
2. Lock 锁
当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突。
import multiprocessing import sys def worker_with(lock, f): with lock: fs = open(f, 'a+') n = 10 while n > 1: fs.write("Lockd acquired via with\n") n -= 1 fs.close() def worker_no_with(lock, f): lock.acquire() try: fs = open(f, 'a+') n = 10 while n > 1: fs.write("Lock acquired directly\n") n -= 1 fs.close() finally: lock.release() if __name__ == "__main__": lock = multiprocessing.Lock() f = "file.txt" w = multiprocessing.Process(target = worker_with, args=(lock, f)) nw = multiprocessing.Process(target = worker_no_with, args=(lock, f)) w.start() nw.start() print "end"
3.Event用来实现进程间同步通信。
import multiprocessing import time def worker(e): print "worker start" e.wait() print ("workder e.is_set()" +str(e.is_set())) def worker_for(e,t): print "worker_for start" e.wait(t) print "worker)for is_set" + str(e.is_set()) e = multiprocessing.Event() w1 = multiprocessing.Process(target=worker,args=(e,)) w2 = multiprocessing.Process(target=worker_for,args=(e,4)) w1.start() w2.start() time.sleep(3) e.set() print "mail"
4.Queue
def writer_proc(q): try: q.put("this a ") print "put" except Exception as e: print e def reader_proc(q): try: print "get" print q.get() except Exception as e: print e print '1111' pass q = multiprocessing.Queue() writer = multiprocessing.Process(target=writer_proc,args=(q,)) writer.start() reader = multiprocessing.Process(target=reader_proc,args=(q,)) reader.start() #writer.join() #reader.join()
5. Pipe
import multiprocessing import time def proc1(pipe): while True: for i in xrange(1000): print "send : %d" % i pipe.send(i) time.sleep(1) def proc2(pipe): while True: print "proc2 sev:", pipe.recv() time.sleep(2) def proc3(pipe): while True: print "Proc3 rev:" , pipe.recv() time.sleep(1) pipe = multiprocessing.Pipe() print pipe p1 = multiprocessing.Process(target=proc1,args=(pipe[0],)) p2 = multiprocessing.Process(target=proc2,args=(pipe[1],)) #p3 = multiprocessing.Process(target=proc3,args=(pipe[1],)) p1.start() p2.start() #p3.start() p1.join() p2.join() #p3.join()
6. Pool
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
函数解释:
- apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞,apply(func[, args[, kwds]])是阻塞的(理解区别,看例1例2结果区别)
- close() 关闭pool,使其不在接受新的任务。
- terminate() 结束工作进程,不在处理未完成的任务。
- join() 主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用。
执行说明:创建一个进程池pool,并设定进程的数量为3,xrange(4)会相继产生四个对象[0, 1, 2, 4],四个对象被提交到pool中,因pool指定进程数为3,所以0、1、2会直接送到进程中执行,当其中一个执行完事后才空出一个进程处理对象3,所以会出现输出“msg: hello 3”出现在"end"后。因为为非阻塞,主函数会自己执行自个的,不搭理进程的执行,所以运行完for循环后直接输出“mMsg: hark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~”,主程序在pool.join()处等待各个进程的结束。
三、协程
1. greenlet实现协程
Python的 greenlet就相当于手动切换,去执行别的子程序,在“别的子程序”中又主动切换回来。。。
from greenlet import greenlet def test1(): print 123 gr2.switch() print 456 gr2.switch() def test2(): print "abc" gr1.switch() print "def" gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
2. gevent 实现协程
Gevent 是一个第三方库,可以轻松通过gevent实现协程程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
gevent会主动识别程序内部的IO操作,当子程序遇到IO后,切换到别的子程序。如果所有的子程序都进入IO,则阻塞。
参考资料:https://www.cnblogs.com/tkqasn/p/5700281.html
https://www.cnblogs.com/kaituorensheng/p/4445418.html (多进程)
https://www.cnblogs.com/zingp/p/5911537.html (协程)