码迷,mamicode.com
首页 > 编程语言 > 详细

python之路 线程、进程、协程、队列

时间:2016-07-22 06:30:57      阅读:304      评论:0      收藏:0      [点我收藏+]

标签:

一、线程

Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
  
def show(arg):
    time.sleep(1)
    print thread+str(arg)
  
for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()
  
print main thread stop

上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。

更多方法:

    • start            线程准备就绪,等待CPU调度
    • setName      为线程设置名称
    • getName      获取线程名称
    • setDaemon   设置为后台线程或前台线程(默认)
                         如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
                          如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
    • join              逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
    • run              线程被cpu调度后自动执行线程对象的run方法
技术分享
import threading
import time
 
 
class MyThread(threading.Thread):
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num
 
    def run(self):#定义每个线程要运行的函数
 
        print("running on number:%s" %self.num)
 
        time.sleep(3)
 
if __name__ == __main__:
 
    t1 = MyThread(1)
    t2 = MyThread(2)
    t1.start()
    t2.start()
自定义线程类

线程锁(Lock、RLock)

由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。

技术分享
#!/usr/bin/env python
#-*-coding:utf-8-*-
import threading
import time
NUM=10

def func(i,l):
    global NUM
    #上锁
    l.acquire()
    NUM -= 1
    time.sleep(5)
    print(NUM)
    #开锁
    l.release()

#lock=threading.Lock()
# lock=threading.RLock()
lock=threading.BoundedSemaphore(5)
for i in range(10):
    # t=threading.Thread(target=func,args=(lock,))
    t=threading.Thread(target=func,args=(i,lock,))
    t.start()
lock、Rlock
技术分享
#!/usr/bin/env python
#-*-coding:utf-8-*-
import threading
def func(i,e):
    print(i)
    e.wait()#检测是什么灯,
    print(i+100)
event=threading.Event()

for i in range(10):
    t=threading.Thread(target=func,args=(i,event,))
    t.start()

#--------------
event.clear()#设置成红灯
inp=input(>>>)
if inp == "1":
    event.set()#设置成绿灯
event锁
技术分享
#!/usr/bin/env python
#-*-coding:utf-8-*-
#第一种
import threading

def condition():
    ret = False
    r = input(>>>)
    if r == true:
        ret = True
    else:
        ret = False
    return ret


def func(i,con):
    print(i)
    con.acquire()
    con.wait_for(condition)
    print(i+100)
    con.release()

c = threading.Condition()
for i in range(10):
    t = threading.Thread(target=func, args=(i,c,))
    t.start()
#第二种
import threading
def func(i,con):
    print(i)
    con.acquire()
    con.wait()
    print(i+100)
    con.release()

c = threading.Condition()
for i in range(10):
    t = threading.Thread(target=func, args=(i,c,))
    t.start()

while True:
    inp = input(>>>)
    if inp == q:
        break
    c.acquire()
    c.notify(int(inp))
    c.release()
from threading import Timer


def hello():
    print("hello, world")

t = Timer(1, hello)
t.start()  # after 1 seconds, "hello, world" will be printed
条件 Condition
技术分享
#互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

import threading,time
 
def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s" %n)
    semaphore.release()
 
if __name__ == __main__:
 
    num= 0
    semaphore  = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()
信号量(Semaphore)

二、进程

from multiprocessing import Process
import threading
import time
  
def foo(i):
    print ‘say hi‘,i
  
for i in range(10):
    p = Process(target=foo,args=(i,))
    p.start()

 注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。

进程间的数据共享

 

#!/usr/bin/env python
#-*-coding:utf-8-*-

#第一种multiprocessing,queues
# from multiprocessing import Process
# from multiprocessing  import queues
# import multiprocessing
#
# def foo(i,arg):
#     arg.put(i)
#     print(‘say hi‘,i,arg.qsize())
#
# if __name__==‘__main__‘:
#     li = queues.Queue(20,ctx=multiprocessing)
#     for i in range(10):
#         p = Process(target=foo,args=(i,li,))
#         p.start()

#第二种Array
# from multiprocessing import Process
# from multiprocessing import queues
# import multiprocessing
# from multiprocessing import Array
# def foo(i,arg):
#     arg[i]=i+100
#     for item in arg:
#         print(item)
#     print(‘==========‘)
# if __name__==‘__main__‘:
#     li=Array(‘i‘,10)
#     for i in range(10):
#         p=Process(target=foo,args=(i,li,))
#         p.start()


#第三种
from multiprocessing import Process
from multiprocessing import queues
import multiprocessing
from multiprocessing import Manager
def foo(i,arg):
    # arg.put(i)
    # print(‘say hi‘,i,arg.qsize())
    # arg[i] = i + 100
    # for item in arg:
    #     print(item)
    # print(‘==========‘)
    arg[i]  = i + 100
    print(arg.values())
if __name__ == ‘__main__‘:
    #li = []
    #li = queues.Queue(20,ctx=multiprocessing)
    obj = Manager()
    li = obj.dict()
    #li = Array(‘i‘,10)
    for i in range(10):
        p = Process(target=foo,args=(i,li,))
        #p.daemon = True
        p.start()
        #p.join()
        import time
        time.sleep(0.1)
技术分享
    c: ctypes.c_char,  u: ctypes.c_wchar,
    b: ctypes.c_byte,  B: ctypes.c_ubyte,
    h: ctypes.c_short, H: ctypes.c_ushort,
    i: ctypes.c_int,   I: ctypes.c_uint,
    l: ctypes.c_long,  L: ctypes.c_ulong,
    f: ctypes.c_float, d: ctypes.c_double
Array_类型对应表

进程锁实例:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from multiprocessing import Process, Array, RLock

def Foo(lock,temp,i):
    """
    将第0个数加100
    """
    lock.acquire()
    temp[0] = 100+i
    for item in temp:
        print i,‘----->‘,item
    lock.release()

lock = RLock()
temp = Array(‘i‘, [11, 22, 33, 44])

for i in range(20):
    p = Process(target=Foo,args=(lock,temp,i,))
    p.start()

 进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

进程池中有两个方法:

  • apply
  • apply_async
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from  multiprocessing import Process,Pool
import time
  
def Foo(i):
    time.sleep(2)
    return i+100
  
def Bar(arg):
    print arg
  
pool = Pool(5)
#print pool.apply(Foo,(1,))
#print pool.apply_async(func =Foo, args=(1,)).get()
  
for i in range(10):
    pool.apply_async(func=Foo, args=(i,),callback=Bar)
  
print ‘end‘
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

 三、协程

 线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。

协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
 
from greenlet import greenlet
 
 
def test1():
    print 12
    gr2.switch()
    print 34
    gr2.switch()
 
 
def test2():
    print 56
    gr1.switch()
    print 78
 
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

 

import gevent
 
def foo():
    print(‘Running in foo‘)
    gevent.sleep(0)
    print(‘Explicit context switch to foo again‘)
 
def bar():
    print(‘Explicit context to bar‘)
    gevent.sleep(0)
    print(‘Implicit context switch back to bar‘)
 
gevent.joinall([
    gevent.spawn(foo),
    gevent.spawn(bar),
])

四、队列

#!/usr/bin/env python
#-*-coding:utf-8-*-
import queue,time
#先进先出队列
#put放数据,是否阻塞,阻塞时的超时时间
#get取数据(默认阻塞),是否阻塞,阻塞时的超时时间
#队列最大长度
#qsize()真是个数
#maxsize最大支持个数
#join,task_done,阻塞进程,当队列中的任务执行完毕后,不再阻塞
# q=queue.Queue(2)
# print(q.empty())#判断队列有没有元素,有返回True
# q.put(11)
# q.put(22)
# print(q.empty())
# print(q.qsize())
# q.put(22)
# q.put(33,block=False)
# q.put(33,block=False,timeout=2)
# print(q.get())
# print(q.get())
# print(q.get(timeout=2))



import  queue               #先进先出
# q = queue.LifoQueue()
# q.put(123)
# q.put(456)
# print(q.get())

# q = queue.PriorityQueue()   #根据优先级处理
# q.put((1,"alex1"))
# q.put((2,"alex2"))
# q.put((3,"alex3"))
# print(q.get())

# q= queue.deque()          #双向队列
# q.append((123))
# q.append(234)
# q.appendleft(456)
# print(q.pop())
# print(q.popleft())



# q=queue.Queue(5)
# q.put(123)
# q.put(456)
# q.get()
# q.task_done()
# q.get()
# time.sleep(5)
# q.task_done()
# q.join()

 

python之路 线程、进程、协程、队列

标签:

原文地址:http://www.cnblogs.com/zhangkui/p/5693749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!