1、python 线程
Threading 用于提供线程相关的操作,线程是应用程序中工作最小的单元。
1 #-*-coding:utf-8-*- 2 #!/usr/bin/env python 3 __author__ = 'bravexz' 4 5 import threading 6 import time 7 8 def show(arg): 9 time.sleep(1) 10 print "thread"+str(arg) 11 12 for i in range(10): 13 t = threading.Thread(target=show,args=(i,)) 14 t.start() 15 16 print "main thread stop"
上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行命令。
- start 线程准备就绪,等待CPU调度
- setName 为线程设置名称
- getName 获取线程名称
- setDaemon 设置为后台线程或前台线程(默认)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 - join 逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
- run 线程被cpu调度后执行Thread类对象的run方法
2、线程锁
由于线程之间是进行随机调度,并且每个线程可能只执行n条指令之后,CPU接着执行其他线程,所以可能出现如下问题:
1 import time 2 import threading 3 4 g1_num = 0 5 def show(arg): 6 global g1_num 7 time.sleep(1) 8 g1_num +=1 9 print g1_num 10 11 for i in range(10): 12 t = threading.Thread(target=show,args=(i,)) 13 t.start() 14 print "main thread stop"
为了解决上面的问题,我们加入了线程锁机制,能够很好的解决以上问题了。
1 import threading 2 import time 3 4 g1_num = 0 5 lock = threading.RLock() 6 def Func(): 7 lock.acquire() 8 global g1_num 9 g1_num +=1 10 time.sleep(1) 11 print g1_num 12 lock.release() 13 14 for i in range(10): 15 t = threading.Thread(target=Func) 16 t.start()
3、event
python 线程的事件用于主线程控制其他线程的执行,事件主要提供了三种方法:set、wait、clear。
事件处理的机制:全文定义一个“Flag”,如果“Flag”值为False,那么当程序执行 event.wait方法时就会阻塞,如果“Flag”值为True,那么event.wait方法时便不再阻塞。
- clear:将“Flag”设置为False
- set:将“Flag”设置为True
1 import threading 2 3 def do(event): 4 print "start" 5 event.wait() 6 print "execute" 7 8 event_obj = threading.Event() 9 for i in range(10): 10 t = threading.Thread(target=do,args=(event_obj,)) 11 t.start() 12 13 event_obj.clear() 14 inp = raw_input("input:") 15 if inp == "true": 16 event_obj.set()
4、python 进程
1 from multiprocessing import Process 2 import threading 3 import time 4 5 def foo(i): 6 print "say hi",i 7 8 for i in range(10): 9 p = Process(target=foo,args=(i,)) 10 p.start()
输入结果:
say hi 0
say hi 1
say hi 4
say hi 3
say hi 5
say hi 7
say hi 9
say hi 2
say hi 8
say hi 6
注明:以上代码必须在linux才可以正常运行。
4.1 进程数据共享
进程各自持有一份数据,默认无法共享数据
1 from multiprocessing import Process 2 from multiprocessing import Manager 3 import time 4 5 li = [] 6 def foo(i): 7 li.append(i) 8 print "say,hi",li 9 10 if __name__ == "__main__": 11 for i in range(10): 12 p = Process(target=foo,args=(i,)) 13 p.start() 14 print "ending",li
输出结果:
ending []
ending []
say,hi [3]
ending []
say,hi [6]
ending []
say,hi [2]
ending []
say,hi [7]
ending []
say,hi [0]
ending []
say,hi [4]
ending []
say,hi [8]
ending []
say,hi [1]
ending []
say,hi [9]
ending []
say,hi [5]
如果解决这个问题呢,看下图:
1 from multiprocessing import Process,Array 2 temp = Array("i",[11,22,33,44]) 3 4 def Foo(i): 5 temp[i] = 100+i 6 for item in temp: 7 print i,"------>",item 8 9 if __name__ == "__main__": 10 for i in range(2): 11 p = Process(target=Foo,args=(i,)) 12 p.start()
输出结果:
0 ------> 100
0 ------> 22
0 ------> 33
0 ------> 44
1 ------> 11
1 ------> 101
1 ------> 33
1 ------> 44
1 from multiprocessing import Process,Manager 2 manage = Manager() 3 dic = manage.dict() 4 def Foo(i): 5 dic[i] = 100+i 6 print dic.values() 7 for i in range(2): 8 p = Process(target=Foo,args=(i,)) 9 p.start() 10 p.join()
输出结果:
[root@centos6 lab]# python oldboy10.1.py
[100]
[100, 101]
当创建进程时(非使用时),共享数据会被拿到子进程中,当进程执行完毕后,再赋值给原值。
一下为进程锁实例:
1 from multiprocessing import Process, Array, RLock 2 3 def Foo(lock,temp,i): 4 lock.acquire() 5 temp[0] = 100+i 6 for item in temp: 7 print i,'----->',item 8 lock.release() 9 10 lock = RLock() 11 temp = Array('i', [11, 22, 33, 44]) 12 13 for i in range(5): 14 p = Process(target=Foo,args=(lock,temp,i,)) 15 p.start()
执行、运行结果:
[root@centos6 lab]# python oldboy10.2.py
0 -----> 100
0 -----> 22
0 -----> 33
0 -----> 44
2 -----> 102
2 -----> 22
2 -----> 33
2 -----> 44
3 -----> 103
3 -----> 22
3 -----> 33
3 -----> 44
4 -----> 104
4 -----> 22
4 -----> 33
4 -----> 44
1 -----> 101
1 -----> 22
1 -----> 33
1 -----> 44
[root@centos6 lab]#
4.2、进程池
进程池内部维护一个进程序列,当使用时,去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:
- apply
- apply_async
1 from multiprocessing import Process,Pool 2 import time 3 4 def Foo(i): 5 time.sleep(2) 6 return i+100 7 def Bar(arg): 8 print arg 9 pool = Pool(5) 10 11 for i in range(10): 12 pool.apply_async(func=Foo,args=(i,),callback= Bar) 13 print "end" 14 pool.close() 15 pool.join()
输出结果如下:
[root@centos6 lab]# python oldboy10.3.py
end
100
102
104
103
101
106
109
108
107
105
[root@centos6 lab]#
5、协程
线程与进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。
协程存在的意义:用于多线程的应用,CPU通过切片的方式来切换线程间的执行,而线程切换时需要耗时(保存状态,下次继续)。协程则只使用一个线程,在一个线程中规定某个代码块执行顺序。
协程的适用场景:当程序中存在大量不需要CPU的操作时(I/O),适用于协程。