在之前的文章中虽然咱们没有介绍过线程这个概念,可是实际上前面全部代码都是线程,只不过是单线程,代码由上而下依次执行或者进入main函数执行,这样的单线程也称为主线程。python
有了单线程的话,什么又是多线程?能够这么理解:一个线程执行一个代码块,多个线程能够同时执行多个代码,使用多线程能让程序效率更高。举个例子,你今天有两件事须要完成,分别是洗衣服和打扫房间,分别来看看单线程和多线程如何完成:git
单线程:先用洗衣机洗衣服30分钟,等衣服洗完以后再打扫房间60分钟,累计总耗时:90分钟;github
多线程:把衣服放到洗衣机而且30分钟后自动结束,而后马上开始打扫房间60分钟,累计耗时:60分钟;微信
因而可知,完成一样的事情,单线程是一件事情作完以后继续下一件事情,而多线程能够同时执行多件事情,因此多线程比单线程效率更高!多线程
线程是cpu最小调度单位,一个程序中至少有一个或者多个线程(至于进程暂时不作讲解,后面文章会有详细解释)!在开发中使用线程可让程序运行效率更高,多线程相似于同时执行多个不一样代码块。ide
1函数 2学习 |
# 导入线程threading模块spa import threading线程 |
调用threading模块中的缺省函数Thread,建立并初始化线程,返回线程句柄。若是对缺省函数已经忘记的小伙伴请回到 python函数的声明和定义中关于缺省参数部分复习一下。
1 2 |
# 建立并初始化线程,返回线程句柄 t = threading.Thread(target=函数名) |
经过初始化返回的线程句柄调用start()函数,启动线程,此时会自动执行在建立线程时target对应的函数内部的代码:
1 2 |
# 启动线程 t.start() |
综合上面三点,下面使用代码对python线程thread作详细讲解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# !usr/bin/env python # -*- coding:utf-8 _*- """ @Author:何以解忧 @Blog(我的博客地址): shuopython.com @WeChat Official Account(微信公众号):猿说python @Github:www.github.com
@File:python_thread.py @Time:2019/10/16 21:02
@Motto:不积跬步无以致千里,不积小流无以成江海,程序人生的精彩须要坚持不懈地积累! """ # 导入线程threading模块 import threading # 导入内置模块time import time
def wash_clothes(): print("洗衣服开始...") # sleep 5 秒,默认以秒为单位 time.sleep(5) print("洗衣服完成...")
def clean_room(): print("打扫房间开始...") # sleep 5 秒,默认以秒为单位 time.sleep(5) print("打扫房间完成...")
if __name__ == "__main__":
# 建立线程并初始化 -- 该线程执行wash_clothes中的代码 t1 = threading.Thread(target=wash_clothes) # 建立线程并初始化 -- 该线程执行clean_room中的代码 t2 = threading.Thread(target=clean_room)
t1.start() t2.start() |
输出结果:
1 2 3 4 |
洗衣服开始... 打扫房间开始... 洗衣服完成... 打扫房间完成... |
运行程序能够发现程序从运行开始到结束,一共耗时5秒时间!注意观察输出日志:
一:洗衣服开始和打扫房间开始几乎同时开始,两个事件同时执行.
二:程序中止5秒;
三:洗衣服和打扫房间几乎同时完成
固然你也能够按照之前的学习的内容,先调用wash_clothes函数,在调用clean_room函数,一样能输出内容,而耗时倒是10秒左右,示例代码以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 导入内置模块time import time
def wash_clothes(): print("洗衣服开始...") # sleep 5 秒,默认以秒为单位 time.sleep(5) print("洗衣服完成...")
def clean_room(): print("打扫房间开始...") # sleep 5 秒,默认以秒为单位 time.sleep(5) print("打扫房间完成...")
if __name__ == "__main__":
wash_clothes() clean_room() |
输出结果:
1 2 3 4 |
洗衣服开始... 洗衣服完成... 打扫房间开始... 打扫房间完成... |
运行程序能够发现程序从运行开始到结束,一共耗时10秒时间!注意观察输出日志:
一:洗衣服开始;
二:程序中止了5秒;
三:洗衣服完成,打扫房间开始
四:程序中止5秒;
五:打扫房间结束,程序结束;
因而可知:多线程能够同时运行多个任务,效率远比单线程更高!
在上面的demo中,咱们并无为线程传递参数,若是在线程中须要传递参数怎么办呢?
threading.Thread()函数中有两个缺省参数 args 和 kwargs ,args 是元组类型,kwargs 是字典类型,缺省值默认为空,除此以外,其实还能够设置线程的名字等,其函数声明以下:
(ps:若是对缺省函数已经忘记的小伙伴请回到 python函数的声明和定义中关于缺省参数部分复习一下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None): """This constructor should always be called with keyword arguments. Arguments are:
*group* should be None; reserved for future extension when a ThreadGroup class is implemented.
*target* is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
*name* is the thread name. By default, a unique name is constructed of the form "Thread-N" where N is a small decimal number.
*args* is the argument tuple for the target invocation. Defaults to ().
*kwargs* is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If a subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.
""" |
示例代码以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# 导入线程threading模块 import threading # 导入内置模块time import time
def wash_clothes(*args,**kargcs): print("wash_clothes:",args) print("wash_clothes:", kargcs)
def clean_room(*args,**kargcs): print("clean_room:",args) print("clean_room:", kargcs)
if __name__ == "__main__":
t1 = threading.Thread(target=wash_clothes, args=(1,"猿说python"), # args 传递元组,能够同时传递多个数据 kwargs={"a":1,"b":False}) # kwargs 传递字典,能够同时传递多个键值对
t2 = threading.Thread(target=clean_room, args=(2,False), # args 传递元组,能够同时传递多个数据 kwargs={"c":0.2,"d":False}) # kwargs 传递字典,能够同时传递多个键值对
t1.start() t2.start() |
值得思考的是:在上面这份代码中一共有几个线程呢?并不是两个,一共是三个线程:
线程一:__name__ == “__main__” 做为主线程;
线程二:t1 做为子线程;
线程三:t2 做为子线程;
注意:主程序会等待全部子程序结束以后才会结束!
1.threading.Thread() — 建立线程并初始化线程,能够为线程传递参数 ;
2.threading.enumerate() — 返回一个包含正在运行的线程的list;
3.threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果;
4.Thread.start() — 启动线程 ;
5.Thread.join() — 阻塞函数,一直等到线程结束为止 ;
6.Thread.isAlive() — 返回线程是否活动的;
7.Thread.getName() — 返回线程名;
8.Thread.setName() — 设置线程名;
9.Thread.setDaemon() — 设置为后台线程,这里默认是False,设置为True以后则主线程不会再等待子线程结束才结束,而是主线程结束意味程序退出,子线程也当即结束,注意调用时必须设置在start()以前;
简单的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# 导入线程threading模块 import threading # 导入内置模块time import time
def wash_clothes(*args,**kargcs): time.sleep(2) print("wash_clothes:",args) time.sleep(2) print("wash_clothes:", kargcs)
def clean_room(*args,**kargcs): time.sleep(2) print("clean_room:",args) time.sleep(2) print("clean_room:", kargcs)
if __name__ == "__main__":
t1 = threading.Thread(target=wash_clothes, args=(1,"猿说python"), # args 传递元组,能够同时传递多个数据 kwargs={"a":1,"b":False}) # kwargs 传递字典,能够同时传递多个键值对
t2 = threading.Thread(target=clean_room, args=(2,False), # args 传递元组,能够同时传递多个数据 kwargs={"c":0.2,"d":False}) # kwargs 传递字典,能够同时传递多个键值对
# setDaemon(True)意味着主线程退出,无论子线程执行到哪一行,子线程自动结束 # t1.setDaemon(True) # t2.setDaemon(True) t1.start() t2.start()
print("threading.enumerate():",threading.enumerate()) print("threading.activeCount():", threading.activeCount()) print("t1.isAlive():",t1.isAlive()) print("t1.getName():", t1.getName()) print("t2.isAlive():", t2.isAlive()) t2.setName("my_custom_thread_2") print("t2.getName():", t2.getName()) |
输出结果:
1 2 3 4 5 6 7 8 9 10 |
threading.enumerate(): [<_MainThread(MainThread, started 18388)>, <Thread(Thread-1, started 16740)>, <Thread(Thread-2, started 17888)>] threading.activeCount(): 3 t1.isAlive(): True t1.getName(): Thread-1 t2.isAlive(): True t2.getName(): my_custom_thread_2 clean_room: (2, False) wash_clothes: (1, '猿说python') wash_clothes: {'a': 1, 'b': False} clean_room: {'c': 0.2, 'd': False} |
1.默认主线程会等待全部子线程结束以后才会结束,主线程结束意味着程序退出;若是setDaemon设置为True,主线程则不会等待子线程,主线程结束,子线程自动结束;
2.threading模块除了以上经常使用函数,还有互斥锁Lock/事件Event/信号量Condition/队列Queue等,因为篇幅有限,后面文章再一一讲解!!
转载请注明:猿说Python » python线程建立和传参