python开发基础篇:六:多线程

线程可以分为:***内核线程:**由操作系统内核创建和撤销。

因为线程的划分尺度小于进程,使得多线程程序的并发性高。

但是通常说**进程、线程同步**,往往特指多进程、线程编程时,多个进程、线程之间**协同步调,按预定的先后次序进行运行**。

IO密集型代码(文件处理、网络爬虫等设计文件读写操作),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序的执行效率。

,”

总结起来,使用多线程编程具有如下几个优点:进程之间不能共享内存,但线程之间共享内存非常容易。

python代码的执行由python虚拟机来控制,即Python先把代码(.py文件)编译成字节码(字节码在Python虚拟机程序里对应的是PyCodeObject对象,.pyc文件是字节码在磁盘上的表现形式),交给字节码虚拟机,然后虚拟机一条一条执行字节码指令,从而完成程序的执行。

注意:join方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。

另外,还可以通过调用诸如thread.exit之类的退出函数,或者sys.exit之类的退出Python进程的标准方法,亦或者抛出SystemExit异常,来使线程退出。

或许这个例子不是很好,也或许是Python3中自动加了锁。

这样就刚好可以充分利用CPU避免CPU处于闲置状态,提高效率。

在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。

但是如果多线程任务都是计算型,CPU会一直在进行工作,直到一定的时间后采取多线程时间切换的方式进行切换线程,此时CPU一直处于工作状态,此种情况下并不能提高性能,相反在切换多线程任务时,可能还会造成时间和资源的浪费,导致效能下降。

重复上述步骤。

操作系统在创建进程时,需要为该进程重新分配系统资源,但创建线程的代价则小得多。

你可以自己构造微线程的调度器,也可以使用greenlet实现高级的控制流。

操作系统在创建进程时,必须为改进程分配独立的内存空间,并分配大量的相关资源,但创建线程则简单得多。

使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要**每次只允许一个线程操作的数据**,可以将其操作放到acquire和release方法之间。

fromtimeimportctime,sleepdefmusic:foriinrange(2):print”Iwaslisteningtomusic.%s”%ctimesleep(1)defmovie:foriinrange(2):print”Iwasatthemovies!%s”%ctimesleep(5)if__name__==\__main__\:musicmovieprint”allover%s”%ctime我们先听了一首音乐,通过for循环来控制音乐的播放了两次,每首音乐播放需要1秒钟,sleep来控制音乐播放的时长。

线程的共享环境包括进程代码段、进程的共有数据等,利用这些共享的数据,线程之间很容易实现通信。

,”

defrun(n):print(task,n)time.sleep(1)print(3s)time.sleep(1)print(2s)time.sleep(1)print(1s)if__name__==__main__:t=threading.Thread(target=run,args=(t1,))t.setDaemon(True)t.start()print(end)通过执行结果可以看出,设置守护线程之后,当主线程结束时,子线程也将立即结束,不再执行主线程等待子线程结束为了让守护线程执行结束之后,主线程再结束,我们可以使用join方法,让主线程等待子线程执行defrun(n):print(task,n)time.sleep(2)print(5s)time.sleep(2)print(3s)time.sleep(2)print(1s)if__name__==__main__:t=threading.Thread(target=run,args=(t1,))t.setDaemon(True)把子线程设置为守护线程,必须在start()之前设置t.start()t.join()设置主线程等待子线程结束print(end)多线程共享全局变量线程时进程的执行单元,进程时系统分配资源的最小执行单位,所以在同一个进程中的多线程是共享资源的g_num=100defwork1():globalg_numforiinrange(3):g_num+=1print(inwork1g_numis:%d%g_num)defwork2():globalg_numprint(inwork2g_numis:%d%g_num)if__name__==__main__:t1=threading.Thread(target=work1)t1.start()time.sleep(1)t2=threading.Thread(target=work2)t2.start()由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以出现了线程锁,即同一时刻允许一个线程执行操作。

如果任务属于是I/O密集型,若不采用多线程,我们在进行I/O操作时,势必要等待前面一个I/O任务完成后面的I/O任务才能进行,在这个等待的过程中,CPU处于等待状态,这时如果采用多线程的话,刚好可以切换到进行另一个I/O任务。

*第二种:开启守护线程*开启线程的setDaemon(True)),设置子线程为守护线程,实现主程序结束,子程序立马全部结束功能*代码演示:

-*-coding:utf-8-*-importthreadingimporttimedeflight:count=1event.set设置标志位TruewhileTrue:ifcount<=10:print("现在是绿灯")time.sleep(1)elifcount<=15:print("现在是红灯")event.clear清空标志位(将标志位改为false)time.sleep(1)else:count=0event.setcount+=1defcar(name):whileTrue:ifevent.is_set:print("----------%s在起飞-------------"%name)time.sleep(1)else:print("---------%s在等红灯---------------"%name)event.wait等待标志位被设置位True程序才继续往下运行event=threading.Eventlight_1=threading.Thread(target=light)light_1.startforxinrange(5):car_1=threading.Thread(target=car,args=("马自达"+str(x),))car_1.start红绿灯案例**Queue(队列)**queue.Queue(maxsize=0)队列:先进先出maxsize:设置队列的大小queue.LifoQueue(maxsize=0)lastinfisrtoutmaxsize:设置队列的大小queue.PriorityQueue(maxsize=0)存储数据时可设置优先级的队列,按优先级顺序(最低的先)maxsize:设置队列的大小**_exception_`queue.``Empty`**Exceptionraisedwhennon-blocking`get`(or`get_nowait`)iscalledona`Queue`objectwhichisempty.当在一个空的队列对象上调用非阻塞的get(或get_nowait)时,会产生异常。

操作系统在创建进程时,必须为改进程分配独立的内存空间,并分配大量的相关资源,但创建线程则简单得多。

如果python程序或者函数开始执行了,你也可以说线程开始执行了。

但是在python中,无论有多少个核同时只能执行一个线程。

python多线程锁有Lock/Rlock,全局锁GIL。

创建多线程python支持两种创建多线程的方式:~通过threading.Thread()创建。

虽然music每首歌曲从1秒延长到了4,但通多程线的方式运行脚本,总的时间没变化。