1)同步、异步
函数或方法被调用的时候,调用者是否得到最终的结果。
- 直接得到最终结果的结果,就是同步调用。(打饭模型,打饭不打好不走开,直到打饭给我后才离开)
- 不直接得到的最终的结果,就是异步调用。(打饭,不会一直等着,会时不时的过来看看,打完了把饭拿走,异步不保证多长时间打完了饭)
2)阻塞、非阻塞:
函数或方法调用的时候,是否立即返回。
- 立即返回就是非阻塞调用。
- 不立即返回就是阻塞调用。
3)区别:
4)联系:
定义
- 进程: 一个运行起来的程序或者软件叫做进程,进程是操作系统分配资源的 基本单位
- 线程:指进程内的一个执行单元,也是进程内的可调度实体。
- 协程:是一种程序组件,是由子例程(过程、函数、例程、方法、子程序)的概念泛化而来的,子例程只有一个入口点且只返回一次,而协程允许多个入口点,可以在指定位置挂起和恢复执行。
区别
线程与进程的区别
协程与线程的比较
函数
# 线程
from threading import Thread
# 线程间队列
import queue
# 进程、进程间队列
from multiprocessing import Process, Queue
#时间模块
import time
#注:线程队列与进程队列不通用,可以通过 as 创建 昵称
#进程间队列:from multiprocessing import Queue as PQueue
#线程间队列:from queue import Queue as QQueue
# 进程一的线程一
# 将数据放入线程间的队列
def process1_thread1(q1):
l = [1, 2, 3]
for i in l:
q1.put(i)
print("进程一的线程一放第{}数据....".format(i))
# 进程一的线程二
# 从线程中取出放入进程间的队列
def process1_thread2(q1, q2):
while True:
try:
data = q1.get(timeout=2)
print("进程一的线程二取数据:",data)
q2.put(data)
print("进程一的线程二放数据....")
except:
break
# 进程二的线程一
# 放入线程间的队列
def process2_thread1(q2, q3):
while True:
try:
data = q2.get(timeout=2)
print("进程二的线程一取数据:",data)
q3.put(data)
print("进程二的线程一放数据....")
except:
break
# 进程二的线程二
# 从线程间的队列取出并输出
def process2_thread2(q3):
while True:
try:
data = q3.get(timeout=2)
print("进程二的线程二取数据....",data)
except:
break
def process1(q2):
# 创建线程间的队列
q1 = queue.Queue()
# 创建进程一的两个线程
p1t1 = Thread(target=process1_thread1, args=(q1,))
p1t2 = Thread(target=process1_thread2, args=(q1, q2))
# 启动两个线程
p1t1.start()
p1t2.start()
# 阻塞,防止死机
p1t1.join()
p1t2.join()
def process2(q2):
# 创建线程间通信
q3 = queue.Queue()
# 创建进程二的两个线程
p2t1 = Thread(target=process2_thread1, args=(q2, q3))
p2t2 = Thread(target=process2_thread2, args=(q3,))
# 启动两个线程
p2t1.start()
p2t2.start()
# 阻塞,防止死机
p2t1.join()
p2t2.join()
if __name__ == '__main__':
# 创建进程间队列
q2 = Queue()
#创建进程一
p1 = Process(target=process1, args=(q2,))
#启动进程一
p1.start()
#创建进程二
p2 = Process(target=process2, args=(q2,))
#启动进程二
p2.start()
函数
from threading import Thread
import requests
import time
import UserAgent
from queue import Queue
base_url = 'https://careers.tencent.com/tencentcareer/api/post/Query?timestamp=1562211235205&countryId=&cityId=&bgIds=&productId=&categoryId=&parentCategoryId=&attrId=&keyword=python&pageIndex={}&pageSize=10&language=zh-cn&area=cn'
headers = UserAgent.getUserAgentC()
def getUrl_and_putData(q,q2):
while True:
try:
url = q.get(timeout = 2)
response = requests.get(url,headers = headers).json()
data = response["Data"]["Posts"][0]["RecruitPostName"]
q2.put(data)
except:
break
def getData(q2):
while True:
try:
data = q2.get(timeout = 2)
print(data)
time.sleep(1)
except:
if flag:
print("没有数据了,退出...")
break
else:
print("队列中还没数据,等待ing...")
if __name__ == '__main__':
flag = False
q = Queue()
q2 = Queue()
for i in range(75):
url = base_url.format(i)
q.put(url)
for i in range(1,4):
t = Thread(target=getUrl_and_putData,args=(q,q2))
t.start()
t.join()
for i in range(1,4):
t = Thread(target=getData,args=(q2,))
t.start()
flag = True
类
#导入程序所用到的资源
from threading import Thread
from queue import Queue
import requests
#随机获取请求头
from fake_useragent import UserAgent
#定义起始URL
base_url = 'https://careers.tencent.com/tencentcareer/api/post/Query?timestamp=1562211235205&countryId=&cityId=&bgIds=&productId=&categoryId=&parentCategoryId=&attrId=&keyword=python&pageIndex={}&pageSize=10&language=zh-cn&area=cn'
headers = {"User-Agent": UserAgent().random}
#生产者
class Produce(Thread):
def __init__(self,name,url_q,data_q):
#继承父类初始化方法
super().__init__()
self.name =name
self.url_q = url_q
self.data_q = data_q
#重写run方法
def run(self):
while True:
try:
#从url队列中取出url
url = self.url_q.get(timeout=1)
print(self.name,url)
#获取页面资源并将其转换为json格式
response = requests.get(url,headers = headers).json()
#将数据放入data队列
self.data_q.put(response)
except:
break
#消费者
class Consumer(Thread):
def __init__(self,name,data_q):
#继承父类初始化方法
super().__init__()
self.name = name
self.data_q = data_q
#重写run方法
def run(self):
while True:
try:
#将数据从data队列中取出
data = self.data_q.get(timeout=1)
#输出json中所需要的数据
print(self.name,data["Data"]["Posts"][0]["RecruitPostName"])
except:
# 如果flag为true时退出循环
if flag:
break
#主函数
if __name__ == '__main__':
#创建队列
url_q = Queue()
data_q = Queue()
#定义一个退出标志
flag = False
#将拼接url
for i in range(1,75):
url = base_url.format(i)
#将url放入url队列中
url_q.put(url)
#定义消费者名称列表
C_list = ["萧炎","林动","牧尘"]
#定义生产者名称列表
P_list = ["阿猫","阿狗","阿猪"]
#定义线程列表
P_thread_list = []
#创建生产者线程
for p_name in P_list:
p = Produce(p_name,url_q,data_q)
p.start()
#创建消费者进程
for c_name in C_list:
c = Consumer(c_name,data_q)
c.start()
#主线程任务结束之后,进入阻塞状态,
# 一直等待其他的子线程执行结束之后,主线程在终止
for p_t in P_thread_list:
p_t.join()
#阻止主线程终止,子线程结束后,将flag标志置为True,线程中的循环方可退出
flag = True