Python网络编程学习_Day10

一、进程与线程

1.区别

进程:一个程序要运行时所需要的所有资源的集合,进程是资源的集合。

一个进程至少需要一个线程,这个线程称为主线程

一个进程里面可以有多个线程

两个进程之间的数据是完全独立,不能互相访问。

线程:一道单一的指令控制流,寄生在进程中。

单一进程里多个进程是共享数据的,多个线程在涉及修改同一个数据时,要加锁。

2.线程调用方法

import threading
import time
 
def sayhi(num): #定义每个线程要运行的函数
 
    print("running on number:%s" %num)
 
    time.sleep(3)
 
if __name__ == '__main__':
 
    t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
    t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
 
    t1.start() #启动线程
    t2.start() #启动另一个线程
 
    print(t1.getName()) #获取线程名
    print(t2.getName())

  

 1 import threading
 2 import time
 3  
 4 def sayhi(num): #定义每个线程要运行的函数
 5  
 6     print("running on number:%s" %num)
 7  
 8     time.sleep(3)
 9  
10 if __name__ == '__main__':
11  
12     t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
13     t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
14  
15     t1.start() #启动线程
16     t2.start() #启动另一个线程
17  
18     print(t1.getName()) #获取线程名
19     print(t2.getName())

3.守护线程

守护线程一旦退出,其子线程都会退出。

代码举例如下:

 1 import time
 2 import threading
 3  
 4  
 5 def run(n):
 6  
 7     print('[%s]------running----\n' % n)
 8     time.sleep(2)
 9     print('--done--')
10  
11 def main():
12     for i in range(5):
13         t = threading.Thread(target=run,args=[i,])
14         t.start()
15         t.join(1)
16         print('starting thread', t.getName())
17  
18  
19 m = threading.Thread(target=main,args=[])
20 m.setDaemon(True) #将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务
21 m.start()
22 m.join(timeout=2)
23 print("---main thread done----")

4.线程锁

多个线程修改同一个数据时要加锁。

 1 import time
 2 import threading
 3  
 4 def addNum():
 5     global num #在每个线程中都获取这个全局变量
 6     print('--get num:',num )
 7     time.sleep(1)
 8     lock.acquire() #修改数据前加锁
 9     num  -=1 #对此公共变量进行-1操作
10     lock.release() #修改后释放
11  
12 num = 100  #设定一个共享变量
13 thread_list = []
14 lock = threading.Lock() #生成全局锁
15 for i in range(100):
16     t = threading.Thread(target=addNum)
17     t.start()
18     thread_list.append(t)
19  
20 for t in thread_list: #等待所有线程执行完毕
21     t.join()
22  
23 print('final num:', num )

5.semaphore(信号量)

 1 import threading,time
 2  
 3 def run(n):
 4     semaphore.acquire()
 5     time.sleep(1)
 6     print("run the thread: %s\n" %n)
 7     semaphore.release()
 8  
 9 if __name__ == '__main__':
10  
11     num= 0
12     semaphore  = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
13     for i in range(20):
14         t = threading.Thread(target=run,args=(i,))
15         t.start()
16  
17 while threading.active_count() != 1:
18     pass #print threading.active_count()
19 else:
20     print('----all threads done---')
21     print(num)

6.Event

event有三个指令,event.set(),event.wait(),event.clear(),通过event实现多个线程间的交互。

交通指挥灯实例:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Liumj
 4 import threading
 5 import time
 6 def lighter():
 7     count = 0
 8     while True:
 9         if count<30:
10             if not event.is_set():
11                 event.set()
12             print("\033[32;1m绿灯--\033[0m")
13         elif count <34:
14             print("\033[33;1m黄灯--\033[0m")
15         elif count<60:
16             if event.is_set():
17                 event.clear()
18             print("\033[31;1m红灯--\033[0m")
19         else:
20             count = 0
21         count +=1
22         time.sleep(0.5)
23 def car(n):
24     count = 0
25     while True:
26         event.wait()
27         print("car [%s] is running..." % n)
28         count +=1
29         time.sleep(1)
30 event = threading.Event()
31 red_light = threading.Thread(target=lighter)
32 red_light.start()
33 c1 = threading.Thread(target=car,args=(2,))
34 c1.start()
View Code

二、queue队列

三种类型:

class queue.Queue(maxsize=0) #先入先出
class queue.LifoQueue(maxsize=0) #last in fisrt out 
class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Liumj
 4 import queue
 5 #q = queue.Queue(maxsize = 2) #先进先出
 6 #q = queue.LifoQueue() #后进先出
 7 q = queue.PriorityQueue(maxsize=3) #后进先出
 8 #q.put(1)
 9 #q.put(2)
10 #q.put(3)
11 q.put([1,"alex"])
12 q.put([5,"eric"])
13 q.put([3,"liumj"])
14 print(q.empty())
15 print(q.full())
16 print(q.get())
17 print(q.get())
18 print(q.get())

三、生产者消费者模型

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。

 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Liumj
 4 import threading
 5 import queue
 6 import time
 7 def consumer(name):
 8     while True:
 9         print("%s 取到骨头[%s]吃了" %(name,q.get()))
10         time.sleep(0.5)
11 def producer(name):
12     count = 0
13     while q.qsize() <5:
14         print("%s 生产了骨头" %name,count)
15         q.put(count)
16         count+=1
17         time.sleep(3)
18 q = queue.Queue(maxsize=4)
19 p = threading.Thread(target=producer,args=("alex",))
20 p2 = threading.Thread(target=producer,args=("eric",))
21 c = threading.Thread(target=consumer,args=("李闯",))
22 p.start()
23 p2.start()
24 c.start()

四、多进程

multiprocessing是一个包,它支持使用类似于线程模块的API来生成进程。 多进程包提供本地和远程并发,通过使用子进程而不是线程有效地旁路全局解释器锁。 因此,多处理模块允许编程人员充分利用给定机器上的多个处理器。 它在Unix和Windows上运行

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Liumj
 4 from multiprocessing import Process,Manager
 5 def f(d,l,n):
 6     d[n] = n
 7     l.append(n)
 8     #print(l)
 9 if __name__ =="__main__":
10     with Manager() as manager:
11         d = manager.dict()
12         l = manager.list(range(5))
13         p_list=[]
14         for i in range(10):
15             p = Process(target=f,args=(d,l,i))
16             p.start()
17             p_list.append(p)
18         for res in p_list:
19             res.join()
20         print(d)
21         print(l)

五、进程间通信

不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:

 1 from multiprocessing import Process, Queue
 2  
 3 def f(q):
 4     q.put([42, None, 'hello'])
 5  
 6 if __name__ == '__main__':
 7     q = Queue()
 8     p = Process(target=f, args=(q,))
 9     p.start()
10     print(q.get())    # prints "[42, None, 'hello']"
11     p.join()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Liumj
from multiprocessing import Process,Pipe
def f(conn):
    conn.send([42,None,'hello'])
    conn.send([41,None,'hello'])
    print("from parent",conn.recv())
    print("from 2",conn.recv())
if __name__ == '__main__':
    parent_conn,child_conn = Pipe()
    p = Process(target=f,args=(child_conn,))
    p.start()
    print(parent_conn.recv())
    parent_conn.send('hello son')
    p.join()

manager多进程

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Liumj
 4 from multiprocessing import Process,Manager
 5 def f(d,l,n):
 6     d[n] = n
 7     l.append(n)
 8     #print(l)
 9 if __name__ =="__main__":
10     with Manager() as manager:
11         d = manager.dict()
12         l = manager.list(range(5))
13         p_list=[]
14         for i in range(10):
15             p = Process(target=f,args=(d,l,i))
16             p.start()
17             p_list.append(p)
18         for res in p_list:
19             res.join()
20         print(d)
21         print(l)
22 
23 输入结果:
24 {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
25 [0, 1, 2, 3, 4, 3, 2, 1, 0, 6, 4, 8, 5, 7, 9]
View Code

六、进程池

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

from  multiprocessing import Process,Pool
import time
 
def Foo(i):
    time.sleep(2)
    return i+100
 
def Bar(arg):
    print('-->exec done:',arg)
 
pool = Pool(5)
 
for i in range(10):
    pool.apply_async(func=Foo, args=(i,),callback=Bar)
    #pool.apply(func=Foo, args=(i,))
 
print('end')
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

 

posted @ 2016-12-12 23:10  liumj  阅读(171)  评论(0编辑  收藏  举报