Python自学第九周(2)

时间:2019-08-09
本文章向大家介绍Python自学第九周(2),主要包括Python自学第九周(2)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
子线程编程守护线程    当主线程结束,不管子线程结束没有,全部结束
 
 1 #Author: Zachary
 2 import threading,time
 3 def run(n):
 4     print("task",n)
 5     time.sleep(2)
 6     print("task done",n,threading.current_thread())
 7 start_time = time.time()
 8 t_objs = []
 9 for i in range(50):
10     t= threading.Thread(target=run,args=("t-%s"%i ,))
11     t.setDaemon(True)         #把当前线程设置为守护线程
12     t.start()
13     t_objs.append(t)
14  
15 print("-----------------all threads has finished")
16 print("cost:",time.time() - start_time)
17 ##将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务
 
GIL锁(线程锁)也称之为互斥锁
如果是在windows上运行
 1 #Author: Zachary
 2 import threading,time
 3 def run(n):
 4     global  num
 5     num += 1
 6  
 7 num = 0
 8 t_objs = []
 9 for i in range(50):
10     t= threading.Thread(target=run,args=("t-%s"%i ,))
11     t.start()
12     t_objs.append(t)
13 for t in t_objs:
14     t.join()
15 print("-----------------all threads has finished")
16 print("num:",num)
 
如果在linux上运行
 1 # -*- coding:utf-8 -*-
 2 #Author: Zachary
 3  
 4 import threading,time
 5 def run(n):
 6    global  num
 7    time.sleep(2)
 8    num += 1
 9 num = 0
10 t_objs = []
11 for i in range(10000):
12    t= threading.Thread(target=run,args=("t-%s"%i ,))
13    t.start()
14    t_objs.append(t)
15 for t in t_objs:
16    t.join()
17 print("-----------------all threads has finished")
18 print("num:",num)
在linux上运行此代码
结果会是
改进后加入了lock,无论在哪个平台怎么运行都不会出错
 1 #Author: Zachary
 2 import threading,time
 3 def run(n):
 4     lock.acquire()
 5     global  num
 6     num += 1
 7     lock.release()
 8 lock = threading.Lock()
 9 num = 0
10 t_objs = []
11 for i in range(50):
12     t= threading.Thread(target=run,args=("t-%s"%i ,))
13     t.start()
14     t_objs.append(t)
15 for t in t_objs:
16     t.join()
17 print("-----------------all threads has finished")
18 print("num:",num)
RLock(递归锁)
在一个大锁中还要再包含子锁
 1 #Author: Zachary
 2 import threading, time
 3  
 4 def run1():
 5     print("grab the first part data")
 6     lock.acquire()
 7     global num
 8     num += 1
 9     lock.release()
10     return num
11  
12 def run2():
13     print("grab the second part data")
14     lock.acquire()
15     global num2
16     num2 += 1
17     lock.release()
18     return num2
19  
20 def run3():
21     lock.acquire()
22     res = run1()
23     print('--------between run1 and run2-----')
24     res2 = run2()
25     lock.release()
26     print(res, res2)
27  
28 num, num2 = 0, 0
29 lock = threading.RLock()
30 for i in range(10):
31     t = threading.Thread(target=run3)
32     t.start()
33 while threading.active_count() != 1:
34     print(threading.active_count())
35 else:
36     print('----all threads done---')
37     print(num, num2)
 
Semaphore(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
 
 1 #Author: Zachary
 2 import threading, time
 3  
 4 def run(n):
 5     semaphore.acquire()               #信号量获取
 6     time.sleep(1)
 7     print("run the thread: %s\n" % n)
 8     semaphore.release()               #信号量释放
 9  
10 semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行
11 for i in range(22):
12      t = threading.Thread(target=run, args=(i,))
13      t.start()
14 while threading.active_count() != 1:
15     pass  # print threading.active_count()
16 else:
17     print('----all threads done---')
 
Events
An event is a simple synchronization object;
the event represents an internal flag, and threads
can wait for the flag to be set, or set or clear the flag themselves.
 
 
event = threading.Event()
# a client thread can wait for the flag to be set
event.wait()
# a server thread can set or reset it
event.set()
event.clear()
If the flag is set, the wait method doesn’t do anything.
标志位设定了,代表绿灯,直接通行
If the flag is cleared, wait will block until it becomes set again.
标志位被清空,代表红灯,wait等待变绿灯
Any number of threads may wait for the same event.
通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
例子
简易的红绿灯切换
 1 #Author: Zachary
 2 import time,threading
 3 event = threading.Event()
 4  
 5 def lighter():
 6     count = 0
 7     while True:
 8         if count > 20 and count < 30:   #改成红灯
 9             event.clear()   #把标志位清空
10             print("\033[41;1mred light is on...\033[0m")
11         elif count > 30:
12             event.set()  #变绿灯
13             count = 0
14         else:
15             print("\033[42;1mgreen light is on...\033[0m")
16         time.sleep(1)
17         count += 1
18 light = threading.Thread(target=lighter,)
19 light.start()
加上小汽车
 1 #Author: Zachary
 2 import time,threading
 3 event = threading.Event()
 4  
 5 def lighter():
 6     count = 0
 7     event.set()
 8     while True:
 9         if count > 5 and count < 10:   #改成红灯
10             event.clear()   #把标志位清空
11             print("\033[41;1mred light is on...\033[0m")
12         elif count > 10:
13             event.set()  #变绿灯
14             count = 0
15         else:
16             print("\033[42;1mgreen light is on...\033[0m")
17         time.sleep(1)
18         count += 1
19 def car(name):
20     while True:
21         if event.is_set():   #代表绿灯
22             print("[%s] running..."%name)
23             time.sleep(1)
24         else:
25             print("[%s] sees red light,waiting..."%name)
26             event.wait()
27             print("\033[34;1m[%s] green is on,start going...\033[0m"%name)
28  
29 light = threading.Thread(target=lighter,)
30 light.start()
31 car1 = threading.Thread(target=car,args=("Tesla",))
32 car1.start()
 
queue队列
queue is especially useful in threaded programming when information must be exchanged safely between multiple threads.
 
class queue.Queue(maxsize=0) #先入先出
class queue.LifoQueue(maxsize=0) #last in fisrt out
class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列
 
Queue.qsize()
Queue.empty() #return True if empty  
Queue.full() # return True if full
Queue.put(item, block=True, timeout=None)
Queue.get(block=True, timeout=None)
Queue.task_done()
例子
 
 1 #Author: Zachary
 2 import queue
 3 print("先进先出")
 4 q = queue.Queue()    #先进先出
 5 q.put("d1")
 6 q.put("d2")
 7 q.put("d3")
 8 print(q.qsize())
 9 print(q.get())
10 print(q.get())
11 print(q.get())
12 # print(q.get())     #不会打印结果
13 # print(q.get_nowait())
14 # print(q.get(block=False))   #结果与上面一行一致
15 q = queue.Queue(maxsize=3)
16 q.put(1)
17 q.put(2)
18 q.put(3)
19 # q.put(4)      #不会进入队列
20 print("=============================\n")
21  
22 print("后进先出")
23 q = queue.LifoQueue()     #后进先出-栈
24 q.put(1)
25 q.put(2)
26 q.put(3)
27 print(q.get())
28 print(q.get())
29 print(q.get())
30 print("=============================\n")
31  
32 print("设置优先级")
33 q = queue.PriorityQueue()
34 q.put((10,"Zach"))
35 q.put((-1,"Zachary"))
36 q.put((6,"Jack"))
37 q.put((3,"Ajax"))
38 print(q.get())
39 print(q.get())
40 print(q.get())
41 print(q.get())
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
 1 #Author: Zachary
 2 import threading,time,queue
 3 q = queue.Queue()
 4 def Producer(name):
 5     count = 1
 6     while True:
 7         q.put("骨头%s"%count)
 8         print("生产了骨头,",count)
 9         count += 1
10         time.sleep(0.5)
11 def Consumer(name):
12     # while q.qsize() :
13     while True:
14         print("[%s] 取到叻[%s] 并且吃了它..."%(name,q.get()))
15         time.sleep(1)
16  
17 p = threading.Thread(target=Producer,args=("Zach",))
18 c = threading.Thread(target=Consumer,args=("Jack",))
19 c2 = threading.Thread(target=Consumer,args=("Ajax",))
20 p.start()
21 c.start()
22 c2.start()

原文地址:https://www.cnblogs.com/zachary26626/p/11329443.html