前提
首先我们需要了解下我们为什么需要学习多线程,他有什么好处呢?
1.使用线程可以把占据长时间的程序中的任务放到后台去处理。
2.基本不会出现线程占用的问题。
3.可以提高程序的运行效率
对于多线程的理解
在多线程的程序中,主线程可以理解为一个饭店的前台,专门用来接待客人,当接收到任务的时候,主线程(前台)就会将任务送到厨房去,交给厨师们去处理(子线程),不会占用自己招待其他客人的时间。
这样做还可以避免线程占用的问题。就比如说写一个服务器的程序,如果不是采用的多线程(异步调用)的方式的话,如果在主线程中还在运行上一个客人的请求的时候,又来了一个新的任务,那么主线程就无法去处理那个新的任务,导致webservice无法被调用,从而出现错误。
使用多线程的方式
目前python中使用多线程的方式有两种,分别是采用threading模块,以及_thread模块。博主这里推荐大家去使用threading模块去写多线程的应用,因为threading模块几乎包含了_thread模块的所有方法并且在原来的基础上新增了很多的方法,可以说用_thread模块能做出来的,用threading模块也可以做出来。
使用_thread模块去写多线程
我们可以调用_thread模块中的start_new_thread()函数来产生新的线程,语法如下:
thread.start_new_thread ( function, args, [kwargs])
·function - 想要在子线程运行的方法。
·args - 传递给线程函数的参数,传递的时候必须是个tuple类型。
·kwargs - 可选参数。
实例代码:
import time//引入时间模块
import _thread//引入_thread模块
//希望在多线程中运行的函数
def print_time(threadName,delay):
count=0
while count <3:
count+=1
time.sleep(delay)
print(threadName+time.ctime(time.time()))
try:
_thread.start_new_thread(print_time,("thread1",1))//将参数变成元组后传给函数
_thread.start_new_thread(print_time,("thread2",2))//将参数变成元组后传给函数
//创建多线程失败
except:
print("error")
while 1:
pass//按ctrl+c结束程序
结果为:
thread1Sun Sep 1 20:22:03 2019
thread2Sun Sep 1 20:22:04 2019
thread1Sun Sep 1 20:22:04 2019
thread1Sun Sep 1 20:22:05 2019
thread2Sun Sep 1 20:22:06 2019
thread2Sun Sep 1 20:22:08 2019
使用threading模块去写多线程
1:
threading模块不仅包含了_thread模块中的所有方法,还包含了以下几种方法:
threading.currentThread():
返回当前的线程变量。(例如:写在主线程中就是返回的主线程)
threading.enumerate():
返回一个包含目前所有正在运行的线程的列表。
threading.activeCount():
返回正在运行的线程数量。
2:
除了使用方法外,threading模块还提供了用来给线程类来处理线程的一些方法:
run():
用来表示线程具体活动的方法。
start():
启动目标线程。(开始调用目标的run()函数)
join([time]):
等待至线程中止或者是超出可选的参数:time。
isAlive():
返回目标线程是否活动的布尔值。
getName():
返回目标线程的名字。
setName():
设置线程的名字。
import time//引入time模块
import threading//引入threading模块
class myThread(threading.Thread):
def __init__(self,threadID,name,counter):
threading.Thread.__init__(self)
self.threadID=threadID
self.name=name
self.couter=counter
def run(self):
print("开始线程"+self.name)
print_time(self.name,self.couter,3)
print("退出线程"+self.name)
def print_time(threadName,delay,counter):
while counter:
time.sleep(delay)
print("%s:%s"%(threadName,time.ctime(time.time())))//显示当前时间
counter-=1
//创建新线程
thread1=myThread(1,'thread1',1)
thread2=myThread(2,'thread2',2)
//开始线程
thread1.start()
thread2.start()
print(threading.active_count())//显示当前处在运行状态的线程的数量(不同编译器出来的值也许会不同)
print(threading.enumerate())//显示当前所有在运行中的线程
thread1.join()//等待线程1结束
thread2.join()//等待线程2结束
print(threading.active_count())
print("退出主线程")
运行结果:(可能会不同)
开始线程thread1
开始线程thread2
9
[<_MainThread(MainThread, started 12024)>, <Thread(ptvsd.EventLoop, started daemon 3764)>, <Thread(ptvsd.Client, started daemon 11440)>, <WriterThread(pydevd.Writer, started daemon 10368)>, <ReaderThread(pydevd.Reader, started daemon 9624)>, <PyDBCommandThread(pydevd.CommandThread, started daemon 11816)>, <CheckOutputThread(pydevd.CheckAliveThread, started 2932)>, <myThread(thread1, started 5848)>, <myThread(thread2, started 7584)>]
thread1:Sun Sep 1 20:41:00 2019
thread2:Sun Sep 1 20:41:01 2019
thread1:Sun Sep 1 20:41:01 2019
thread1:Sun Sep 1 20:41:02 2019
退出线程thread1
thread2:Sun Sep 1 20:41:03 2019
thread2:Sun Sep 1 20:41:05 2019
退出线程thread2
7
退出主线程
总结
python中的多线程我个人感觉使用起来还是很方便的,之前我也写过用C#去写多线程的文章,他的方法有很多种,有用委托的,有用Task的,有用Thread的,有用ThreadPool的,有用async、await的,方法各不相同,相比之下,python的看起来就简单一些。
(PS:不知道为什么,明明是用的python去写的程序,原程序里也是正确的,但是我文章的注释还是忍不住用的“//”而不是“#”…)