线程
多线程--threading
python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用
使用threading模块
importthreading
importtime
defsaySorry():
print("亲爱的,我错了,我能吃饭了吗?")
time.sleep(1)
if__name__ =="__main__":
foriinrange(5):
t = threading.Thread(target=saySorry)
t.start()#启动线程,即让线程开始执行
多线程并发操作,话费的时间要短很多
创建好的线程,需要调用start()方法来启动
主线程会等爱所有的子线程结束后才结束
多线程和多进程一样,执行顺序是不确定的人,如果线程被sleep阻塞,到结束的时候线程进入就绪状态
每个线程会有一个名字,python会自动为线程指定一个名字
当线程的run()方法结束时该线程完成
线程的集中状态:
总结:
在一个进程内的所有线程共享全局变量,能够在不适用其他方式的前提下完成多线程间的数据共享
缺点:
线程对全局变量随意更改可能会造成多线程之间对全局变量的混乱(线程非安全)
进程和线程:
进程:能够完成多任务,比如在一台电脑上能够同时运行多个QQ
线程:能够完成多个任务,比如一个qq的多个聊天窗口
定义的不同
·进程是系统进行资源分配和调度的一个独立单位.
·线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
区别:
一个程序至少有一个进程,一个进程至少有一个线程
线程的划分尺度少于进程(资源比进程少),使得多线程程序的并发性高,
进程在执行过程中拥有独立的内存单元,而对歌线程共享内存,从而极大的提高了程序的运行效率
线程不能够独立执行,必须依存在进程中
优缺点:
线程和进城在使用上各有优缺点,线程执行开销小,但不利于资源的管理和保护,而进程正好相反
同步的概念:
多线程开发可能遇到的问题
同步就是协同步调,按预定的先后次序进运行
互斥锁:
当多个线程几乎同时修改某一个共享数据的时候需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁
互斥锁为资源引入一个状态,锁定/非锁定
某个线程要更改共享数据时,先将其锁定,此时资源的状态为'锁定',其他线程不能更改,知道该线程释放资源,其他线程才能再次锁定该资源
threading.Lock
其中,锁定方法acquire可以有一个bloching参数.
如果设定blocking为true,则当前线程会堵塞,知道获取到这个锁为止,默认为true,如果设定为false,则当前线程不会堵塞
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
注意:
每次只有一个线程可以获得锁,如果此时另一个线程试图获得这个锁,该线程就会变成阻塞状态,只懂啊拥有锁的方法释放锁之后
好处:确保关键代码完整执行:
坏处:
阻止并发执行,使效率降低
可能会造成死锁
多线程,局部数据
在多线程开发中,全局变量是多个线程都共享的数据,而局部变量等是各自线程的,非共享
死锁
两个线程同时等待对方的资源,就会造成死锁
尽量避免(银行家算法)
添加超时时间
queue的说明:
添加数据到队列中,使用put()方法
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
、生产者消费者模式:
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这个阻塞队列就是用来给生产者和消费者解耦的。纵观大多数设计模式,都会找一个第三者出来进行解耦