python--进程,线程,协程

进程

进程的相关概念:http://www.cnblogs.com/chaguang/p/7818440.html

在python中创建进程用到了multiprocessing中的Process类

创建进程,使用Process中的def __init__(self, group=None, target=None, name=None, args=(), kwargs={})
参数:
  • target:表示调用对象
  • args:表示调用对象的位置参数元组
  • kwargs:表示调用对象的字典
  • name:为别名
  • group:实质上不使用

方法:

  • is_alive():如果进程是运行的,返回True
  • join([timeout]):主进程是否等待子进程结束,没有传递超时时间timeout则为等待子进程结束,如果设置了timeout,表示最多等待timeout时间
  • run():运行target参数指定的函数
  • start():启动进程,并调用子进程中的run方法
  • terminate():终止进程,不进行任何清理操作,如果该进程有子进程,那么就会变成僵尸进程
 1 from multiprocessing import Process
 2 g_i=1
 3 def f1(i):
 4     global g_i
 5     g_i+=1
 6     print(i,g_i)
 7 #进程的相关信息必须放在if __name__=="__main__":中,否则会报错
 8 if __name__=="__main__":
 9     for i in range(5):
10         #args后的括号内必须加,
11         p=Process(target=f1,args=(i,))
12         #启动进程
13         p.start()
Process的使用

 注意事项

  1. 在windows中Process()必须放到# if __name__ == '__main__':下
  2. 参数args的括号中必须带,,否则会报错,例如args=(i,)
  3. 进程的数据默认不共享的,各自有一份,所以在创建多进程的时候,系统开销比较大

 进程间的数据共享

  • Array
 1 from multiprocessing import Process,Array
 2 import time
 3 #Array相当于c中的数组,规定类型都需要一样
 4 g_data=Array("i",[1,2,3,4,5,6])
 5     # 类型:
 6     # 'c': ctypes.c_char,  'u': ctypes.c_wchar,
 7     # 'b': ctypes.c_byte,  'B': ctypes.c_ubyte,
 8     # 'h': ctypes.c_short, 'H': ctypes.c_ushort,
 9     # 'i': ctypes.c_int,   'I': ctypes.c_uint,
10     # 'l': ctypes.c_long,  'L': ctypes.c_ulong,
11     # 'f': ctypes.c_float, 'd': ctypes.c_double
12 def sum(i):
13    g_data[i]+=i
14 
15 if __name__=="__main__" :
16     for i in range(6):
17         pro=Process(target=sum,args=(i,))
18         pro.start()
19         pro.join()
Array
  • manage.dict()
 1 from multiprocessing import Process,Manager
 2 
 3 
 4 def sum(dic,i):
 5     if i <5:
 6         dic[i]=i
 7     else:
 8         dic[i]="sdafsd"
 9     print(dic[i],dic.values())
10 
11 if __name__=="__main__" :
12     #创建一个Manager()对象
13     ma = Manager()
14     #创建一个进程间能够共享数据的“字典”,不需要类型统一
15     dic = ma.dict()
16     for i in range(6):
17         pro=Process(target=sum,args=(dic,i,))
18         pro.start()
19         pro.join()
20 
21 
22 
23 
24 
25 
26 #
Manager

进程池

  在python中,multiprocessing模块里提供了Pool的使用

进程池的一些方法:

  • apply:同步执行,内部有调用了join,一个一个执行,主进程等子进程结束,它才结束
  • apply_async:异步执行,并且可以设置回调函数,内部没有调用join,主进程不等子进程结束,可以调用pool对象.join()让主进程等待子进程,但是有一个限制,需要再其前面加p.close()(等任务执行完之后再终止)或者p.terminate()(立即终止所有的任务),调用函数的返回值可以传递给回调函数的参数
  • close:关闭进程池
 1 from multiprocessing import process,Pool
 2 import time
 3 def f1():
 4     print("f1")
 5     time.sleep(2)
 6     return 0
 7 #f2的参数a是调用函数f1的返回值
 8 def f2(a):
 9     print("f2:this is a callback~",a)
10     return 1
11 if __name__=="__main__":
12     #创建一个有5个进程数的进程池
13     pool=Pool(5)
14     for i in range(5):
15         #使用进程池
16         # pool.apply(func=f1)
17         pool.apply_async(func=f1,callback=f2)
18     print("end")
19     pool.close()
20     pool.join()
进程池

线程

线程的相关概念:http://www.cnblogs.com/chaguang/p/7818456.html

全局解释器锁GIL

 

threading模块

                      threading模块中的对象

Thread 表示一个执行线程的对象
Lock 锁原语对象
RLock 可重入锁对象,使单一线程可以获得已持有的锁
Condition 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”
Event 条件变量的通用版本,任意数量的线程等待某个事件发生,在该事件发生后所有的线程都将被激活
Semaphore 为线程间共享的有限资源提供一个“计数器”,如果没有可用资源时,会被阻塞
BoundedSemaphore 与Semaphore相似,不过它不允许超过初始值
Timer 与Thread相似,不过它要在运行前等待一段时间
Barrier 创建一个“障碍”,必须达到指定数量的线程后才可以继续

 

 

 

 

 

 

 

 

 

 

  threading模块中的对象Lock,RLock,Condition,Semaphore和BoundeSemaphore都包含上下文管理器,即可以使用with语句

Thread类

Thread对象的数据属性:

  • name:线程名
  • ident:线程的标识符
  • daemon:布尔标志。表示该线程是否为守护线程,即进程退出的时候不需要等待这个线程执行完成

Thread对象方法:

start()                 开始执行该线程
run()                   定义线程功能的方法(通常在子类中被重写)
join([timeout])         直至启动的线程终止之前一直挂起,除非给出timeout,否则会一直阻塞
getName()               返回线程名
setName(name)           设置线程名
 1 import threading
 2 
 3 class myThread(threading.Thread):
 4     def __init__(self,func,args,name=''):
 5         threading.Thread.__init__(self)
 6         self.name=name
 7         self.func=func
 8         self.args=args
 9         
10     def run(self):
11         self.func(*self.args)
12 def fun(*args):
13     print(args)
14 
15 if __name__=="__main__":
16     obj=myThread(fun,("诸葛",))
17     obj.start()
Thread

 

线程锁Lock和RLock

  为了解决线程同步的问题,python在threading模块中提供了Lock和RLock,互斥锁 同时只允许一个线程更改数据,有两种状态:锁定和未锁定。而且它也支持两个函数:获得锁和释放锁

 1 import threading
 2 
 3 g_num=1
 4 g_lock = threading.RLock()
 5 
 6 class myThread(threading.Thread):
 7     def __init__(self,func,args,name=''):
 8         threading.Thread.__init__(self)
 9         self.name=name
10         self.func=func
11         self.args=args
12 
13     def run(self):
14         self.func(*self.args)
15 def fun(*args):
16     print(args)
17     global g_num
18     #获得锁
19     # g_lock.acquire()
20     # g_num+=100
21     # print(g_num)
22     # g_lock.release()
23     #上面的情况也可以写成with语句中,上下文管理器负责在进入之前调用acquire,执行完之后调用release
24     with g_lock:
25         g_num+=100
26         print(g_num)
27 
28 if __name__=="__main__":
29     for i in range(5):
30         obj=myThread(fun,("诸葛",))
31         obj.start()

 

信号量(Semaphore)

  Semaphore也是为了解决线程同步的问题,与互斥锁不同的是,Semaphore同时允许一定数量的线程更改数据,它是一个计数器,当资源消耗的时候递减,当资源释放的时候递增

 1 import threading
 2 import time
 3 g_num=1
 4 #设置资源数为5,即可以同时被5个线程执行临界区的内容
 5 g_lock = threading.Semaphore(5)
 6 
 7 class myThread(threading.Thread):
 8     def __init__(self,func,args,name=''):
 9         threading.Thread.__init__(self)
10         self.name=name
11         self.func=func
12         self.args=args
13 
14     def run(self):
15         self.func(*self.args)
16 def fun(*args):
17     print("acquire")
18     global g_num
19     # 获得锁
20     g_lock.acquire()
21     print(args[1])
22     time.sleep(2)
23     print("release")
24     #释放锁
25     g_lock.release()
26 
27 
28 if __name__=="__main__":
29     for i in range(5):
30         obj=myThread(fun,("诸葛",1))
31         obj.start()
semaphore

事件(event)

  python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear

 1 from threading import Thread,Event
 2 import time
 3 #创建一个事件对象
 4 event_obj=Event()
 5 
 6 def f1():
 7     print("wait........")
 8     #等待event_obj.set()方法
 9     event_obj.wait()
10     print("start.........")
11 
12 if __name__=="__main__":
13     for i in range(5):
14         thread=Thread(target=f1)
15         thread.start()
16 
17 print("sleeping....")
18 
19 time.sleep(3)
20 event_obj.set()
event

条件(Condition)

 1 import threading
 2 #该函数用来判断条件,返回True的话,con.wait_for()向下执行
 3 def condition_func():
 4     ...
 5     return True
 6 
 7 def run(n):
 8     #获得锁
 9     con.acquire()
10     #当condition_func返回True时候才向下执行,wait_for的参数需要是可以调用的对象
11     con.wait_for(condition_func)
12     print(n)
13     # 释放锁
14     con.release()
15 
16 if __name__ == '__main__':
17     #创建一个condition对象
18     con = threading.Condition()
19     for i in range(10):
20         t = threading.Thread(target=run, args=(i,))
21         t.start()
Condition

Timer

  定时器,指定n秒后才开始执行操作

1 from threading import  Timer
2 def f1():
3     print("start run....")
4 
5 t=Timer(3,f1)
6 t.start()
Timer

线程池

  1 #线程池
  2 import threading
  3 import contextlib
  4 import queue
  5 
  6 #用来当终止符
  7 stopTask=object()
  8 
  9 class ThreadPool(object):
 10     def __init__(self,maxNum,maxTaskNum=None):
 11         if maxTaskNum:
 12             self.taskQueue=queue.Queue(maxTaskNum)
 13         else:
 14             self.taskQueue=queue.Queue()
 15         #最大线程数
 16         self.maxNum=maxNum
 17         #空闲线程
 18         self.freeThread=[]
 19         #正在运行的线程
 20         self.runningThread=[]
 21         #判断是否要终止线程池,清空所有的任务
 22         self.terminate=False
 23     def Run(self,func,args,callback=None):
 24         #如果没有空闲的线程
 25         if len(self.freeThread)==0 or len(self.runningThread)<self.maxNum:
 26             #创建一个线程
 27             self.CreateThread()
 28         lis=(func,args,callback,)
 29         #将任务放在任务列表中
 30         self.taskQueue.put(lis)
 31 
 32     def CreateThread(self):
 33         obj=threading.Thread(target=self.call)
 34         #开始执行线程,让线程去处理任务
 35         obj.start()
 36 
 37     def call(self):
 38         #获取当前线程
 39         currentThread=threading.current_thread()
 40         #将线程添加到正在执行线程的列表中
 41         self.runningThread.append(currentThread)
 42 
 43         #开始取任务,然后处理任务
 44         task=self.taskQueue.get()
 45         while task!=stopTask:
 46             func,args,callback=task
 47             #执行任务中的处理函数,并将其参数传递给func函数
 48             ret=func(*args)
 49             if callback != None:
 50                 #如果回调函数不为空,则将调用结果的返回值传给回调函数
 51                 callback(ret)
 52             #************************************************#
 53             # #处理完任务,重新获取任务
 54             # self.freeThread.append(currentThread)
 55             # #如果终止符标记符为True,那么就向任务队列中投放终止符
 56             # if self.terminate:
 57             #     #self.taskQueue.put(stopTask)
 58             #     task=stopTask
 59             # else:
 60             #     task=self.taskQueue.get()
 61             # self.freeThread.remove(currentThread)
 62             #***********************************************#
 63             #上面的*号括着的内容等价于下面with里面的内容,主要是因为被@contextlib.contextmanager
 64             #修饰的worker_state函数
 65             with self.worker_state(self.freeThread,currentThread):
 66                 if self.terminate:
 67                     task = stopTask
 68                 else:
 69                     task = self.taskQueue.get()
 70         #收到了终止符号,终止线程
 71         else:
 72             self.runningThread.remove(currentThread)
 73 
 74     def Close(self):
 75         #关闭线程池
 76         threadNum=len(self.runningThread)
 77         while threadNum:
 78             self.taskQueue.put(stopTask)
 79             threadNum-=1
 80 
 81     def Terminate(self):
 82         #立即关闭线程池,清空所有的任务
 83         self.terminate=True
 84         while self.runningThread:
 85             self.taskQueue.put(stopTask)
 86         #清空任务对列
 87         self.taskQueue.queue.clear()
 88     #利用上下文管理
 89     @contextlib.contextmanager
 90     def worker_state(self, state_list, worker_thread):
 91         state_list.append(worker_thread)
 92         try:
 93             yield
 94         finally:
 95             state_list.remove(worker_thread)
 96 
 97 
 98 
 99 def ca(re):
100     print("callback,f1 return value %s"%re)
101 
102 def f1(*args):
103     print(args)
104     return 0
105 
106 obj=ThreadPool(3)
107 
108 for i in range(5):
109     obj.Run(f1,(11,22,33,),ca)
110 
111 obj.Terminate()
线程池

 

协程

  在协程中,控制可以从当前执行上下文跳转到程序的其它位置,并且可以在之后的任意时刻恢复当前执行上下文,控制从跳出点处继续执行。协程主要用在程序中有大量的IO操作的时候,这时候虽然可以用多线程的解决,但是这可能导致多个线程进行等待,这时就可以使用协程来解决,利用一个线程去等待多个IO操作。

 1 from greenlet import greenlet
 2 
 3 def test1():
 4     print("12")
 5     gr2.switch()
 6     print("34")
 7     gr2.switch()
 8 
 9 def test2():
10     print("56")
11     gr1.switch()
12     print("78")
13 
14 gr1 = greenlet(test1)
15 gr2 = greenlet(test2)
16 gr1.switch()
17 ######输出############
18 12
19 56
20 34
21 78
greenlet
 1 # from gevent import monkey; monkey.patch_socket()
 2 import gevent
 3 
 4 def f(n):
 5     for i in range(n):
 6         print(gevent.getcurrent(), i)
 7         gevent.sleep()
 8 
 9 # g1 = gevent.spawn(f, 5)
10 # g2 = gevent.spawn(f, 5)
11 # g3 = gevent.spawn(f, 5)
12 # g1.join()
13 # g2.join()
14 # g3.join()
15 #或者写成下面的形式
16 gevent.joinall([
17     gevent.spawn(f,5),
18     gevent.spawn(f,5),
19     gevent.spawn(f,5),
20 ])
gevent

 

posted @ 2018-03-12 21:09  菜鸟也有高飞的时候  阅读(260)  评论(0编辑  收藏  举报