python 线程创建和传参(28)

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

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

修炼

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

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

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

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

python 线程创建和传参(28)第2张

一.线程解释

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

python 线程创建和传参(28)第3张

二.线程创建和启动

1.导入线程模块

#导入线程threading模块
import threading

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

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

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

3.启动线程

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

#启动线程
t.start()

python 线程创建和传参(28)第4张

综合上面三步,下面使用代码对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模块
importthreading
#导入内置模块time
importtime
 
defwash_clothes():
    print("洗衣服开始...")
    #sleep 5 秒,默认以秒为单位
    time.sleep(5)
    print("洗衣服完成...")
 
defclean_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
importtime
 
defwash_clothes():
    print("洗衣服开始...")
    #sleep 5 秒,默认以秒为单位
    time.sleep(5)
    print("洗衣服完成...")
 
defclean_room():
    print("打扫房间开始...")
    #sleep 5 秒,默认以秒为单位
    time.sleep(5)
    print("打扫房间完成...")
 
if __name__ == "__main__":
 
    wash_clothes()
    clean_room()

输出结果:

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

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

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

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

python 线程创建和传参(28)第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模块
importthreading
#导入内置模块time
importtime
 
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()

python 线程创建和传参(28)第6张

四.线程结束

值得思考的是:在上面这份代码中一共有几个线程呢?并非两个,一共是三个线程:

  • 线程一:__name__ == “__main__” 作为主线程;
  • 线程二:t1 作为子线程;
  • 线程三:t2 作为子线程;

注意:主程序会等待所有子程序结束之后才会结束!

python 线程创建和传参(28)第7张

五.相关函数介绍

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模块
importthreading
#导入内置模块time
importtime
 
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(): 3t1.isAlive(): True
t1.getName(): Thread-1t2.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}

python 线程创建和传参(28)第8张

六.重点总结

1.默认主线程会等待所有子线程结束之后才会结束,主线程结束意味着程序退出;如果setDaemon设置为True,主线程则不会等待子线程,主线程结束,子线程自动结束;

2.threading模块除了以上常用函数,还有互斥锁Lock/事件Event/信号量Condition/队列Queue等,由于篇幅有限,后面文章再一一讲解!!

python 线程创建和传参(28)第9张

猜你喜欢:

1.python模块

2.python匿名函数

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

4.python异常处理

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

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

免责声明:文章转载自《python 线程创建和传参(28)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Libevent:1前言MSBuild version 与 ToolsVersion 的区别下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

一篇文章教会你用Python抓取抖音app热点数据

今天给大家分享一篇简单的安卓app数据分析及抓取方法。以抖音为例,我们想要抓取抖音的热点榜数据。 要知道,这个数据是没有网页版的,只能从手机端下手。 首先我们要安装charles抓包APP数据,它是一款收费的抓包修改工具,易上手,数据请求容易控制,修改简单,抓取数据的开始暂停方便等优势,网上也有汉化版,下载地址为http://www.zdfans.com/...

Jenkins 五: 构建Ant项目

1. 点击“新建”,在“Item名称”栏输入要构建的项目名,比如“Ant_project”,选择“构建一个自由风格的软件项目”,点击“OK”按钮。 2. 找到“源码管理”-> “Subversion”. 在 “Repository URL”栏输入源码地址。 3. 找到“ 构建”。点击 “增加构建步骤”,选择”Invoke Ant”。 在“Ant Ve...

阻塞队列和死锁

BlockingQueue        BlockingQueue是并发容器的一种,在J.U.C的包路径下,是线程安全的一种实现,是基于阻塞队列的,该接口提供了相对于Queue的新的put()和take()操作。put()添加元素时,当阻塞队列满的情况下会阻塞下来,当有空间时才能进行添加操作,添加到队列尾部;take()删除元素时,当队列为空时,也会阻塞...

epoll惊群原因分析

考虑如下情况(实际一般不会做,这里只是举个例子): 在主线程中创建一个socket、绑定到本地端口并监听 在主线程中创建一个epoll实例(epoll_create(2)) 将监听socket添加到epoll中(epoll_ctl(2)) 创建多个子线程,每个子线程都共享步骤2里创建的同一个epoll文件描述符,然后调用epoll_wait(2)等待事...

Python操作Access数据库基本操作步骤分析

Python编程语言的出现,带给开发人员非常大的好处。我们可以利用这样一款功能强大的面向对象开源语言来轻松的实现许多特定功能需求。比如Python操作Access数据库的功能实现等等。在Python操作Access数据库之前,首先,你应安装了Python和Python for Windows extensions(pywin32-216.win32-py2...

C#中的多线程

原文:http://www.albahari.com/threading/part2.aspx 文章来源:http://blog.gkarch.com/threading/part2.html 1同步概要 在第 1 部分:基础知识中,我们描述了如何在线程上启动任务、配置线程以及双向传递数据。同时也说明了局部变量对于线程来说是私有的,以及引用是如何在线程之间...