python day9
本节内容
进程与线程
1.进程:
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。
进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:
-
进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。
-
进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。
2.线程:
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
Python threading模块
线程有2种调用方式,如下:
直接调用
# 直接调用 import time import threading def run(name): print('%s线程执行.....'%name) time.sleep(3) pass t1 =threading.Thread(target=run,args=('A',)) t2 =threading.Thread(target=run,args=('B',)) t1.start() t2.start()
继承调用
# 继承式 import time import threading class MyThread(threading.Thread): def __init__(self,name): super(MyThread,self).__init__() self.name=name pass def run(self): print("running is thread %s"%self.name) time.sleep(3) pass t1=MyThread('C') t2=MyThread('D') t1.start() t2.start()
join:等待线程终止。(线程的合并)
import time import threading class MyThread(threading.Thread): def __init__(self,name): super(MyThread,self).__init__() self.name=name pass def run(self): print("running is thread %s"%self.name) time.sleep(3) pass t1=MyThread('C') t2=MyThread('D') t1.start()#等待t1线程执行完毕在执行t2线程 t1.join() t2.start()
Daemon:设置线程为守护线程
守护线程是:辅助线程,当一个线程为另一个线程的守护线程时,那么如果另一个线程退出,那么守护线程也会退出,在守护线程中开启的线程也会同时退出。
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/6 23:44 # software: PyCharm # 守护线程 import time import threading class MyThread(threading.Thread): def __init__(self, name): super(MyThread, self).__init__() self.name = name pass def run(self): print("running is thread %s" % self.name) time.sleep(3) pass t1 = MyThread('C') t2 = MyThread('D') t1.setDaemon(True)#设置线程为守护线程。 t2.setDaemon(True) t1.start() t2.start() print('mian 主线程执行完毕')
线程锁
线程锁指的是:我们多线程在同时修改一个数据时,每个线程都会拿到同一份数据,那么修改完后数据的结果就会不正确了。
import threading import time num=0 def run(n): global num if n=='A': time.sleep(2) num+=1 print("num", num) else: num+=1 print("num", num) pass t1 = threading.Thread(target=run,args='A') t2=threading.Thread(target=run,args='B') t1.start() t2.start()
加锁后的代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/7 13:34 # software: PyCharm import threading import time # 获取一个锁的实例 lock =threading.Lock() num=0 def run(n): global num lock.acquire()#加锁 if n=='A': print("A",num)#线程A获取的num的值 time.sleep(2) num+=1 print("A修改后num", num) lock.release()#释放锁 else: print("B:",num) #线程B获取的num的值 num+=1 print("B修改后num", num) lock.release() pass t1 = threading.Thread(target=run,args='A') t2=threading.Thread(target=run,args='B') t1.start() t2.start()
注意:在python3上有锁没锁,代码结果都是正确的,可能是python3自动加了锁。
递归锁:
我们可能在使用线程锁的时候,可能出现锁中套者锁,那么这个时候就可能出现,线程退不出来。
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/7 14:33 # software: PyCharm # 递归锁 import threading,time def run1(): print("grab the first part data") lock.acquire() global num num +=1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2+=1 lock.release() return num2 def run3(): lock.acquire() res = run1() print('--------between run1 and run2-----') res2 = run2() lock.release() print(res,res2) num,num2 = 0,0 lock = threading.Lock() for i in range(10): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num,num2)
使用递归锁
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/7 14:33 # software: PyCharm # 递归锁 import threading,time def run1(): print("grab the first part data") lock.acquire() global num num +=1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2+=1 lock.release() return num2 def run3(): lock.acquire() res = run1() print('--------between run1 and run2-----') res2 = run2() lock.release() print(res,res2) num,num2 = 0,0 lock = threading.RLock() for i in range(10): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num,num2)
Semaphore(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据。
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/7 14:42 # software: PyCharm import threading,time def run(n): semaphore.acquire() global num num+=1 time.sleep(1) print("run the thread: %s" %n,num,'\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() while threading.active_count() != 1: pass #print threading.active_count() else: print('----all threads done---') print(num)
Events:
Event(事件)是最简单的线程通信机制之一:一个线程通知事件,其他线程等待事件。Event内置了一个初始为False的标志,当调用set()时设为True,调用clear()时重置为 False。wait()将阻塞线程至等待阻塞状态。
isSet(): 当内置标志为True时返回True。
set(): 将标志设为True,并通知所有处于等待阻塞状态的线程恢复运行状态。
clear(): 将标志设为False。
wait([timeout]): 如果标志为True将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()。
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/7 16:26 # software: PyCharm # 红绿等 import threading import time event=threading.Event() def run(): count=0; while True: if count>5 and count<10: event.clear() print('这是红灯请等待') elif count>10: event.set() count=0 else: print('这是绿灯,请通行') time.sleep(1) count+=1 pass def car(name): while True: if event.is_set(): print('请 赶紧通行',name) else: print("请等待红灯") event.wait() pass h=threading.Thread(target=run,) c=threading.Thread(target=car,args=('奔驰',)) c1=threading.Thread(target=car,args=('宝马',)) h.start() c.start() c1.start()
队列:
queue
queue是用户多线程编程中的,线程之间的通信。
python中有3种队列:
- class
queue.
Queue
(maxsize=0) #先入先出 - class
queue.
LifoQueue
(maxsize=0) #last in fisrt out - class
queue.
PriorityQueue
(maxsize=0) #存储数据时可设置优先级的队列 - queue常用的方法:
- 将一个值放入队列中 put方法
- 将一个值从队列中取出 get方法
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作
#!/usr/bin/env python #-*- coding:utf-8 -*- # author:Dragon war # datetime:2018/9/10 14:16 # software: PyCharm # 队列 queue # 队列使用queue模块 import queue # 创建队列:先进先出 q=queue.Queue() # 往队列中添加 q.put(1) q.put(2) # 队列大小 print(q.qsize()) # 从队列中取值 print(q.get()) print(q.get()) # 如果队列中没有值了,那么再调用get方法,将会阻塞 print(q.get()) while not q.empty(): print(q.get()) qe=queue.LifoQueue() #先进后出 for i in range(5): qe.put(i) pass # 取值 while not qe.empty(): print(qe.get()) # 优先级队列 qq =queue.PriorityQueue() # 添加 qq.put(10,"aaa") qq.put(6,"bbbb") qq.put(12,"cccc") qq.put(3,"ddddd") # 取值 while not qq.empty(): print(qq.get()) pass