在以前的文章中虽然我们没有介绍过线程这个概念,但是实际上前面所有代码都是线程,只不过是单线程,代码由上而下依次执行或者进入main函数执行,这样的单线程也称为主线程。

有了单线程的话,什么又是多线程?可以这么理解:一个线程执行一个代码块,多个线程可以同时执行多个代码,使用多线程能让程序效率更高。举个例子,你今天有两件事需要完成,分别是洗衣服和打扫房间,分别来看看单线程和多线程如何完成:

单线程:先用洗衣机洗衣服30分钟,等衣服洗完之后再打扫房间60分钟,累计总耗时:90分钟;

    多线程:把衣服放到洗衣机并且30分钟后自动结束,然后立刻开始打扫房间60分钟,累计耗时:60分钟;

由此可见,完成同样的事情,单线程是一件事情做完之后继续下一件事情,而多线程可以同时执行多件事情,所以多线程比单线程效率更高!

一.线程解释

线程是cpu最小调度单位,一个程序中至少有一个或者多个线程(至于进程暂时不做讲解,后面文章会有详细解释)!在开发中使用线程可以让程序运行效率更高,多线程类似于同时执行多个不同代码块。

二.线程创建和启动

1.导入线程模块

# 导入线程threading模块
import threading

2.创建线程并初始化线程

调用threading模块中的缺省函数Thread,创建并初始化线程,返回线程句柄。如果对缺省函数已经忘记的小伙伴请回到 python函数的声明和定义中关于缺省参数部分复习一下。

# 创建并初始化线程,返回线程句柄
t = threading.Thread(target=函数名)

3.启动线程

通过初始化返回的线程句柄调用start()函数,启动线程,此时会自动执行在创建线程时target对应的函数内部的代码:

# 启动线程
t.start()

综合上面三步,下面使用代码对python线程thread做详细讲解:

# !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()

输出结果:

洗衣服开始...
打扫房间开始...
洗衣服完成...
打扫房间完成...

运行程序可以发现程序从运行开始到结束,一共耗时5秒时间!注意观察输出日志:

  • 第一步:洗衣服开始和打扫房间开始几乎同时开始,两个事件同时执行.
  • 第二步:程序停止5秒;
  • 第三步:洗衣服和打扫房间几乎同时完成

当然你也可以按照以前的学习的内容,先调用wash_clothes函数,在调用clean_room函数,同样能输出内容,而耗时却是10秒左右,示例代码如下:

# 导入内置模块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()

输出结果:

洗衣服开始...
洗衣服完成...
打扫房间开始...
打扫房间完成...

运行程序可以发现程序从运行开始到结束,一共耗时10秒时间!注意观察输出日志:

  • 第一步:洗衣服开始;
  • 第二步:程序停止了5秒;
  • 第三步:洗衣服完成,打扫房间开始
  • 第四步:程序停止5秒;
  • 第五步:打扫房间结束,程序结束;

由此可见:多线程可以同时运行多个任务,效率远比单线程更高!

三.线程传参

在上面的例子中,我们并没有为线程传递参数,如果在线程中需要传递参数怎么办呢?

threading.Thread()函数中有两个缺省参数 args 和 kwargs ,args 是元组类型,kwargs 是字典类型,缺省值默认为空,除此之外,其实还可以设置线程的名字等,其函数声明如下:

(ps:如果对缺省函数已经忘记的小伙伴请回到 python函数的声明和定义中关于缺省参数部分复习一下)

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. """

示例代码如下:

# 导入线程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()之前;

简单的示例代码:

# 导入线程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())

输出结果:

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等,由于篇幅有限,后面文章再一一讲解!!

猜你喜欢:

1.python模块

2.python匿名函数

3.python不定长参数 *argc,**kargcs

4.python异常处理

转载请注明:猿说Python » python线程创建和传参

技术交流、商务合作请直接联系博主
扫码或搜索:猿说python
猿说python
微信公众号 扫一扫关注

python 线程创建和传参(28)的更多相关文章

  1. 『Python × C++』函数传参机制学习以及对比

    一.Python函数传参 在python中,函数传参实际上传入的是变量的别名,由于python内在的变量机制(名称和变量值相互独立),只要传入的变量不可变(tuple中的元素也要是不可变的才行),那么 ...

  2. 第24课 std::thread线程类及传参问题

    一. std::thread类 (一)thread类摘要及分析 class thread { // class for observing and managing threads public: c ...

  3. python字符串格式化--dict传参

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python字符串格式化--dict传参 print "I'm %(name)s. I'm %(a ...

  4. # Python第十节 传参

    Python第十节 传参 一. 变量和变量名 首先说明变量名和变量的一点差异 例如: var = [1, 2, 3] `var = "Google" 调用变量var的时候, 既可以 ...

  5. python记录_day10 动态传参 命名空间 作用域

    一.动态传参 动态传参用到 *args 和 **kwargs ,*号表示接收位置参数,args是参数名:**表示接收关键字参数,kwargs是参数名 def chi(*food): print(foo ...

  6. python函数的动态传参.作用域与命名空间

    一.动态传参1.*表示动态传参. 可以接受所有的位置参数传参的时候自动的把实参打包成元组 交给形参 def chi(*food): print(food) chi() # 动态传参可以不传参数 chi ...

  7. python基础:函数传参、全局变量、局部变量、内置函数、匿名函数、递归、os模块、time模块

    ---恢复内容开始--- 一.函数相关: 1.1位置参数: ef hello(name,sex,county='china'): pass #hello('hh','nv') #位置参数.默认参数 1 ...

  8. python 传值引用和传参引用

    调用同事的函数,传入goods_list,获取商品信息,然后将商品信息与goods_list的信息进行匹配,合并. 但是同事返回数据的同时改变了我传入的参数,goods_list.相当于传参引用,也就 ...

  9. Java学习小结(1)-数组的创建与传参

    (一)数组的创建 数组的创建包括两部分:数组的申明与分配内存空间. int score[]=null; //申明一维数组 score=new int[3]; //分配长度为3的空间 数组的申明还有另外 ...

随机推荐

  1. DIJ的优化,和spfa的优化

    SPFA和DIJ求最短路的算法的坑点一直是很多的.经常会让人搞不懂. 易错案例: 用重载运算符来排序,如: struct cmp { bool operator ()(int x, int y) co ...

  2. git revert 让提交不再害怕

    git revert 让提交不再害怕 使用了好多命令, 但对于 git revert 一直不敢怎么使用, 为什么呢? 因为 git merge 的存在. 每次 对于 git merge 的分支, 执行 ...

  3. linux设置定时任务的方法步骤

    一,首先登录 二,找到文件夹 三,查看定时任务 crontab -l 四,vi root 编辑定时任务 编辑完成后,点ESC,然后:wq 时间格式 分钟 小时 日期 月份 周 命令 数字范围 0-59 ...

  4. python 二维码

    pip3 install Pillow pip3 install qrcode import qrcode text ="gisoracle我爱你呀" #input("输 ...

  5. delphi 运算符重载

    譬如上面的 record 可以这样声明: type   TMyRec = record     name: string;     age: Word;     class operator Grea ...

  6. Cesium原理篇:6 Renderer模块(1: Buffer)【转】

    https://www.bbsmax.com/A/n2d9P1Q5Dv/ 刚刚结束完地球切片的渲染调度后,打算介绍一下目前大家都很关注的3D Tiles方面的内容,但发现要讲3D Tiles,或者充分 ...

  7. 全新的Unity跨平台开发 IDE JetBrains Rider 2019.2 x64特别版下载

    Rider 基于 JetBrains 的平台,JetBrains 的平台很受那些使用 IntelliJ IDEA 的 Java 开发者和使用 WebStorm 的 JavaScript 开发者的欢迎. ...

  8. windows下更改Apache以fastcgi方式运行php

    Apache 默认 apache2handler 方式运行处理php. 下面说切换方法: 1.下载fastcgi模块,打开https://www.apachelounge.com/download/选 ...

  9. Nfs固定端口 nfs 端口公网映射

  10. Error-JavaScript:SCRIPT1007: 缺少 ']'

    ylbtech-Error-JavaScript:SCRIPT1007: 缺少 ']' SCRIPT1007: 缺少 ']' 1.返回顶部 · if (flag) { return eval(&quo ...