进程之间的相互通信、生产者消费者模型、线程以及创建方式、线程对象以及常用的方法、守护线程、
有关于人工智能一些高端功能的网站:
1、百度api
http://ai.baidu.com/?track=cp:ainsem|pf:pc|pp:tongyong-pinpai|pu:pinpai-baiduAI|ci:|kw:10003812
2、科大讯飞(语音方面很专业)
https://www.xfyun.cn/?ch=bdtg&renqun_youhua=646957
3、图灵机器人
http://www.turingapi.com/
进程之间的相互通信:
队列:先进先出
堆栈:先进后出
代码理解队列:
1 from multiprocessing import Queue 2 q = Queue(5) # 括号内可以传参数 表示的是这个队列的最大存储数 3 # 往队列中添加数据 4 q.put(1) 5 q.put(2) 6 # print(q.full()) # 判断队列是否满了 7 q.put(3) 8 q.put(4) 9 q.put(5) 10 # print(q.full()) 11 # q.put(6) # 当队列满了之后 再放入数据 不会报错 会原地等待 直到队列中有数据被取走(阻塞态) 12 print(q.get()) 13 print(q.get()) 14 print(q.get()) 15 print(q.empty()) # 判断队列中的数据是否取完 16 print(q.get()) 17 print(q.get()) 18 print(q.empty()) 19 # print(q.get_nowait()) # 取值 没有值不等待直接报错 20 # print(q.get()) # 当队列中的数据被取完之后 再次获取 程序会阻塞 直到有人往队列中放入值 21 """ 22 full 23 get_nowait 24 empty 25 都不适用于多进程的情况 26 """
进程间通信的ipc机制:
1 from multiprocessing import Process,Queue 2 3 def producer(q): 4 q.put('hello GF~') 5 6 def consumer(q): 7 print(q.get()) 8 9 if __name__ == '__main__': 10 q = Queue() 11 p = Process(target=producer,args=(q,)) 12 c = Process(target=consumer, args=(q,)) 13 p.start() 14 c.start() 15 16 17 """ 18 子进程放数据 主进程获取数据 19 两个子进程相互放 取数据 20 """
生产者消费者模型:
1 """ 2 生产者:生产/制造数据的 3 消费者:消费/处理数据的 4 例子:做包子的,买包子的 5 1.做包子远比买包子的多 6 2.做包子的远比包子的少 7 供需不平衡的问题 8 """ 9 from multiprocessing import Process,Queue,JoinableQueue 10 import random 11 import time 12 13 14 def producer(name,food,q): 15 for i in range(10): 16 data = '%s生产了%s%s'%(name,food,i) 17 time.sleep(random.random()) 18 q.put(data) 19 print(data) 20 21 def consumer(name,q): 22 while True: 23 data = q.get() 24 if data == None:break 25 print('%s吃了%s'%(name,data)) 26 time.sleep(random.random()) 27 q.task_done() # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了 28 29 30 31 if __name__ == '__main__': 32 q = JoinableQueue() 33 p = Process(target=producer,args=('大厨egon','馒头',q)) 34 p1 = Process(target=producer,args=('跟班tank','生蚝',q)) 35 c = Process(target=consumer,args=('许兆龙',q)) 36 c1 = Process(target=consumer,args=('吃货jerry',q)) 37 p.start() 38 p1.start() 39 c.daemon = True 40 c1.daemon = True 41 c.start() 42 c1.start() 43 p.join() 44 p1.join() 45 46 q.join() # 等到队列中数据全部取出 47 # q.put(None) 48 # q.put(None)
线程:
什么是线程
进程线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物
进程:资源单位
线程:执行单位
将内存比如成工厂
那么进程就相当于是工厂里面的车间
而你的线程就相当于是车间里面的流水线
ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中
提供代码运行所需要的资源
为什么要有线程
开进程
1.申请内存空间 耗资源
2."拷贝代码" 耗资源
一个进程内可以起多个线程,并且线程与线程之间数据是共享的
ps:开启线程的开销要远远小于开启进程的开销
线程的两种创建方式:
方式一:
1 # from threading import Thread 2 # import time 3 # 4 # def task(name): 5 # print('%s is running'%name) 6 # time.sleep(3) 7 # print('%s is over'%name) 8 # # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内 9 # t = Thread(target=task,args=('egon',)) 10 # t.start() # 告诉操作系统开辟一个线程 线程的开销远远小于进程 11 # # 小的代码执行完 线程就已经开启了 12 # print('主')
方式二:
1 from threading import Thread 2 import time 3 4 class MyThread(Thread): 5 def __init__(self,name): 6 super().__init__() 7 self.name = name 8 9 def run(self): 10 print('%s is running'%self.name) 11 time.sleep(3) 12 print('%s is over'%self.name) 13 14 t = MyThread('egon') 15 t.start() 16 print('主')
线程对象以及常用的方法:
1 from threading import Thread,current_thread,active_count 2 import time 3 import os 4 5 def task(name,i): 6 print('%s is running'%name) 7 print('子current_thread:', current_thread().name) 8 print('子',os.getpid()) 9 time.sleep(i) 10 11 print('%s is over'%name) 12 # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内 13 t = Thread(target=task,args=('egon',1)) 14 t1 = Thread(target=task,args=('jason',2)) 15 t.start() # 告诉操作系统开辟一个线程 线程的开销远远小于进程 16 t1.start() # 告诉操作系统开辟一个线程 线程的开销远远小于进程 17 t1.join() # 主线程等待子线程运行完毕再执行 18 #因为这个代码需要等t1运行完毕才执行,所以当在等t1执行结束的过程中t也运行结束所以活跃数为1 19 print('当前正在活跃的线程数',active_count()) 20 # 小的代码执行完 线程就已经开启了,所以不是先打印主 21 print('主') 22 print('主current_thread:',current_thread().name) 23 print('主',os.getpid())
守护线程:
即当主线程结束时,设置的守护子线程也会结束。
daemon:需要设置在start之前。
守护进程的小例子:加深理解!
1 from threading import Thread 2 from multiprocessing import Process 3 import time 4 5 6 def foo(): 7 print(123) 8 time.sleep(1) 9 print("end123") 10 11 12 def bar(): 13 print(456) 14 time.sleep(3) 15 print("end456") 16 17 18 """ 19 因为主线程需要等待其他非守护线程结束才能结束, 20 所以当t1被设置为守护线程之后, 21 理论上当主线程打印完毕后就结束了运行了,不会运行sleep后的代码了 22 但是这个时候t2(非守护线程)的运行并没有结束,所以主线程也不会结束 23 所以线程t1也继续运行。 24 """ 25 26 if __name__ == '__main__': 27 t1 = Thread(target=foo) 28 t2 = Thread(target=bar) 29 t1.daemon = True 30 t1.start() 31 t2.start() 32 print("main-------")
1 from threading import Thread,current_thread 2 import time 3 4 5 def task(i): 6 print(current_thread().name) 7 time.sleep(i) 8 print('GG') 9 10 11 for i in range(3): 12 t = Thread(target=task,args=(i,)) 13 # 设置为守护线程后,主线程结束,子线程立马结束。 14 t.daemon = True 15 t.start() 16 print('主') 17 18 # t = Thread(target=task,args=(1,)) 19 # t.daemon = True 20 # t.start() 21 # print('主') 22 # 主线程运行结束之后需要等待子线程结束才能结束呢? 23 """ 24 主线程的结束也就意味着进程的结束 25 主线程必须等待其他非守护线程的结束才能结束 26 (意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了) 27 """
线程之间的数据是共享的:
验证代码:
1 from threading import Thread 2 money = 666 3 def task(): 4 global money 5 money = 999 6 t = Thread(target=task) 7 t.start() 8 t.join() 9 print(money)
互斥锁:
1 from threading import Thread,Lock 2 import time 3 """ 4 在不设置互斥锁时,100个线程同时运行, 5 每个线程得到的数字n都是100,都进行减一,所以结果为99 6 当多个线/进程去处理一个数据时会发生错乱时,需要加锁 7 设置互斥锁之后,锁只需要加在处理数据的部分,100个线程之间进行抢锁, 8 使并发变成了串行,降低了效率,提高了数据的安全性。所以结果变为了0 9 """ 10 11 n = 100 12 13 def task(mutex): 14 global n 15 mutex.acquire() 16 tmp = n 17 time.sleep(0.1) 18 n = tmp - 1 19 mutex.release() 20 21 t_list = [] 22 mutex = Lock() 23 for i in range(100): 24 t = Thread(target=task,args=(mutex,)) 25 t.start() 26 t_list.append(t) 27 for t in t_list: 28 t.join() 29 print(n)