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 (协程)
来源:oschina
链接:https://my.oschina.net/u/4278635/blog/3278404