'''
并发:同一个时间段内运行多个程序的能力
进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据集、进程控制块三部分组成
程序:食谱
数据集:鸡蛋、牛奶、糖等
进程控制块:记下食谱做到哪一步了
线程:最小的执行单元,程序中具体代码 比如:食谱中的具体操作方法
进程:最小的资源管理单元,线程,数据等等 比如:整个食谱
切换的操作者:操作系统
进程/线程切换原则:
1、时间片
2、遇到IO操作切换 代码执行input()函数时,本身不占cpu了,输入完成后再切回来。conn,client_addr = sock.accept()执行后不占cpu了,
开启了另一个有关监听的线程,当接收到数据是再切给accept
串行、并行、并发
并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
所以说,并行是并发的子集
IO密集型任务:程序存在大量IO操作
计算密集型任务:程序存在大量计算操作
对于PYTHON的多线程处理:
IO密集型任务有优势
计算密集型任务不推荐使用多线程
'''
多线程
import threading
import time
def foo(n):
print('>>>>>%s' %n)
time.sleep(3)
def bar(n):
time.sleep(5)
print('>>>>>%s' %n)
s = time.time()
t1 = threading.Thread(target=foo,args=(2,))
t1.start() # .start()方法激活线程,可以去抢cpu执行
t2 = threading.Thread(target=bar,args=(5,))
t2.setDaemon(True) # 主线程结束不等待子线程
t2.start()
t1.join() # 加入主线程阻塞
# t2.join()
print('ending!')
print('cost time:',time.time()-s)
线程的类继承式创建
import threading
import time
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
# super().__init__()
def run(self):
print('OK')
time.sleep(2)
print('end t1')
t1 = MyThread()
t1.start()
print('ending')
线程三把锁
互斥锁
import threading
import time
def sub():
global num
lock.acquire()
temp = num
time.sleep(0.1)
num = temp-1
lock.release()
time.sleep(2)
num = 100
lock = threading.Lock()
l = []
for i in range(100):
t = threading.Thread(target=sub,args=())
t.start()
l.append(t)
for t in l:
t.join()
print(num)
递归锁
import threading
import time
class MyThread(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
self.foo()
self.bar()
def foo(self):
RLock.acquire()
print('I am %s GET LOCKA-----%s' %(self.name,time.ctime()))
RLock.acquire()
print('I am %s GET LOCKB-----%s' %(self.name,time.ctime()))
RLock.release()
# time.sleep(1)
RLock.release()
# time.sleep(1)
def bar(self):
RLock.acquire()
print('I am %s GET LOCKA-----%s' %(self.name,time.ctime()))
# time.sleep(1)
RLock.acquire()
print('I am %s GET LOCKB-----%s' %(self.name,time.ctime()))
RLock.release()
# time.sleep(2)
RLock.release()
RLock = threading.RLock()
# LockB = threading.Lock()
for i in range(10):
t = MyThread()
t.start()
信号量
import threading
import time
semaphore = threading.Semaphore(10)
def foo():
semaphore.acquire()
print('OK')
time.sleep(1)
semaphore.release()
for i in range(100):
t = threading.Thread(target=foo,args=())
t.start()
event对象
import threading,time
event = threading.Event() # 默认isSet()=False,加.wait()阻塞
def foo():
while not event.is_set():
print('wait.....')
event.wait(2)
print('Connect to redis server')
for i in range(5):
t = threading.Thread(target=foo,args=())
t.start()
print('attempt to start redis server')
time.sleep(10)
event.set() # 主线程给子线程set()
队列
队列:基于锁实现的,用于多线程,保证线程安全的一种数据结构
############################################ FIFO先进先出模型
import queue
q = queue.Queue(3) # 参数为队列最大数,不加参数默认无限大
print(q)
q.put(11)
q.put('hello')
# q.put(3.14)
q.put(555,block = False) # 阻塞,如果队列满,报错
# q.put(555) # 大于最大值,会阻塞,等待队列中数据被拿走后在进队列
print(q.get())
print(q.get())
print(q.get())
# print(q.get(block = False)) # 阻塞,如果队空,报错
# print(q.get()) # 队列空后,会阻塞,等待队列被加入
############################################ LIFO后进先出模型
import queue
q = queue.LifoQueue()
q.put(11)
q.put(22)
q.put(33)
while not q.empty():
print(q.get())
############################################ priority优先级模型
import queue
q = queue.PriorityQueue()
q.put([1,'11111']) # []表示一个序列数据类型,也可全部换成()
q.put([1,'00000']) # 优先级相同,优先级按照ascii码顺序
q.put([5,'55555'])
q.put([3,'33333'])
q.put([4,'44444'])
q.put([2,'22222'])
while not q.empty():
print(q.get())
队列的两个方法.join()和.task_done()
两个方法必须配合使用
.join()方法阻塞进程,知道所有任务完成
.task_done()方法在每次队列执行完后必须添加
import queue,threading
q = queue.Queue()
def foo():
q.put(111)
q.put(222)
q.put(333)
q.join()
print('ok')
def bar():
print(q.get())
q.task_done() # 每取一个队列,必须执行一条task_done()
print(q.get())
q.task_done()
print(q.get())
q.task_done()
t1 = threading.Thread(target=foo,args=())
t1.start()
t2 = threading.Thread(target=bar,args=())
t2.start()
'''
队列实例:生产者消费者模型
生产者:创建数据的模型
消费者:获取数据的模型
优点:
1、解耦合
2、实现并发
'''
import queue,threading,time
import random
q=queue.Queue(50)
def Producer(id):
count=1
while count<10: # 一次可做10个包子
if q.qsize()<20: # 当包子数小于20个,厨师才做
s=random.randint(1,100) # 包子代号
q.put(s)
print(id+" has made baozi %s"%s)
time.sleep(1) # 此IO可切线程,每做一个包子换另一个厨师,直到做够最小包子数
count+=1
def Consumer(id):
while True:
s=q.get() # 取包子,s是代号
print("Consumer "+id+" has eat %s"%s)
time.sleep(2)
for i in range(10):
t1=threading.Thread(target=Producer,args=(str(i),))
t1.start()
for i in range(10):
t=threading.Thread(target=Consumer,args=(str(i),))
t.start()