多线程多进程操作
多线程任务处理
多进程任务处理
协程多任务处理
线程(Thread)
程序实际执行者是线程,线程称为轻量级进程,是一个cpu的执行单元,每个进程至少会有一个主线程
多线程编程
Python2中标准模块thread 和threading
Python3中模块_thread和 threading
_thread在最底层操作不易 一般推荐使用threading
_thread模块多线程并发
引入模块
Import _thread
获取当前线程编号
_thread.get_ident()
创建线程并执行函数
_thread.start_new_thread()
Threading模块属性和方法
Thread类型属性和方法
Threading 模块的Thread
全局变量 global
定义函数外的变量赋值
Time.sleep()
让主程序暂停一定的时间,这样可以让子线程在主程序结束前运行结束
Threading.current_thread()
Threading.current_thread().getName()
Threading.get_ident()
获取当前运行线程对象 线程名称 线程端口
Threading.main_thread()
获取主线程对象
T1 = Threading.Thread(name, target, args)
创建线程
Target调用函数def
Args=(“tom”, ) 列表
T1.daemon = True
守护线程 ,当主线程结束,守护线程无论任务执行完成都将随着主线程的结束而结束
T1.start()
启动线程
T1.join()
独占: 让当前线程独占CPU时间片,直到当前线程运行结束
Print(t1.is_alive(),t2.is_alive())
判断线程存活状态,true线程正在运行 false 线程结束运行
当多个线程同时售票时会出现多个线程同售一张票的情况,这时就需要上锁进行独自售票
lock = threading.Lock() 同步锁/互斥锁
Lock = threading.Rlock() 可重用锁
锁的操作
Acquire() 上锁
Release() 解锁
Lock.acquire()
Lock.release()
当多个线程同时售票时需要先上锁然后再运算最后解锁,但是当运行到最后没有数据可以运行时就会结束循环无法解锁,这时就需要再循环外再加一个解锁的代码这样就完成了解锁的操作 不会再出现死锁的情况
死锁 dead lock
死锁时可以尝试使用可重用锁 可重用锁定义一次就行了 但还是会出现死锁的情况
可重用锁在锁定的基础上提供了一个计数器的操作counter,可以通过计算上锁的次数然后通过release解锁时就会重新运算计数器,等待计数器清零时所有的锁就全部释放了
死锁的问题一般遇不到
结束循环
break
事件对象 threading.Event
Set()添加标记
Wait() 线程等待 如果当前事件对象被标记 继续运行
Clear() 清除标记
Threading.Condition()
条件对象
Acquire() 上锁
Release() 解锁
Wait() 等待
Wait_for() 等待
Notify() 唤醒
Notify_all() 唤醒所有
队列 queue
先进先出 后进后出
站
先进后出 后进先出
线程队列
queue.Queue(10) 队列中可以存储的个数
为什么运行的时候生产者和消费者 要分开
异常处理 当try中的数据异常时执行except中的数据 这样程序不会报错
Try:
Except:
单词 范围 range 例:for I in range(5)
回顾列表 list []
添加数据
List.append()
删除数据
List.pop()
移除一个元素 默认最后一个,并且返回该元素的值
多线程的两种实现
函数式的多线程实现
Def
类型式的编程实现
Class
自主创建多个线程对象
T1 = Threading.thread()
T2 = threading.thread()
创建多个线程对象
class MyClazz(threading.Thread):
def __init__(self, name, info):
super().__init__(name=name)
self.info = info
def run(self):
print(self.info, "run()方法是线程执行的核心方法,在线程启动的时候会自动执行;不要自己去调用!")
通过类型创建线程
M1 = MyClass()
M1.start() 启动线程,自动执行创建的对象内部的run方法
Pdf 格式文件 可以将文件保存成pdf格式这样在任何地方打开文件格式都不会改变,并且不能修改
进程(Process)
进程中的属性和方法
Import multiprocessing, os
Os
Getpid(): 获取进程号
Getppid(): 获取父进程编号
Process
Name 进程名称
Ident 进程编号
Daemon 是否守护进程,默认false
Start(): 启动进程
Run(): 进程执行方法
Terminate(): 进程结束
Is_alive(): 判断进程是否存活
Join(): 独占模式,要求当前进程函数返回才能继续执行其他进程
进程和线程的使用方式大致相同
基于函数的多进程
基于类型的多进程
Multiprocessing.Process()
创建函数式进程
多线程模式下我们的全局变量是多个线程共享,
通过两种方式观察多进程模式下的数据处理
全局变量的数据
进程本身是独立运行的,多进程被运行多次,每个进程中的全局变量的数据是独立的
参数数据
多进程并发处理函数传递参数的方式,并不能被多个进程共享
函数执行并发操作是,每个进程都会单独拷贝一份当前进程的变量数据进行独立使用,不会互相影响
多进程的简化操作:进程池
Pool进程池 : 包含并且管理多个进程的一个对象
Multiprocessing.Pool(2)
创建一个进程池,该进程可以产生两个进程
Pool.apply_async(function, args, callback = ) 异步非阻塞执行一个函数
Pool.apply(function, args)同步执行一个函数,当进程中的函数执行完成才能退出 顺序执行
Callback 回调函数
将 download函数中返回的值 return返回值 给save_data(data)再调用
停止提交任务
Pool.close()
停止提交任务时才能向主线程申请内存 否则当主进程运行完成 进程池无法申请内存任务还在提交 并没有开始运行
独占模式: 让主进程等待进程池任务执行完成
Pool.join()
进程池中的进程 默认是主进程的守护进程
进程中操作哦变量数据,是独立的 非共享
多个进程都可以读取到全局变量的值
如何让进程之间完成数据共享|通信
- 通过第三方的东西进行交互
a进程将数据存储到文件|数据库中
b进程从文件|数据库中读取数据
文件|数据库是独立于a和b进程之外的数据类型完成进程之间的通信
通过第三方,独立于进程之外的数据类型完成进程间的通信
事件对象 进程之间的状态标记通信
Event = Multiprocessing.Event()
Event.set()
Event.clear()
Event.wait()
Conditon 条件类型
Queue 数据操作类型
数据共享类型
管道类型 用于进程之间的协作
args(tom, ) 参数传递
只有一个元素加逗号 不加逗号成了一个运算符