2_python高阶_线程—threading模块

简介: python高阶_线程—threading模块

一、线程(重点)

  • python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用。
  • 线程执行的顺序不确定。
  • 如果创建Thread时执行的函数,运行结束那么意味着:这个子线程结束了....
  • 如果主线程提前结束,子线程也会结束(不论子线程是否执行完)。
  • 当调用Thread的时候,不会创建线程。当调用Thread创建出来的实例对象的start方法的时候,才会创建线程以及让这个线程开始执行。
  • 线程结束,函数结束。
  • 主线程最后结束。

1.1 使用threading模块

1.1.1 单线程执行

#coding=utf-8
import time

def saySorry():
    print("亲爱的,我错了,我能吃饭了吗?")
    time.sleep(1)

if __name__ == "__main__":
    for i in range(5):
        saySorry()

1.1.2 多线程执行

#coding=utf-8
import threading
import time

# 定义函数不会执行,调用函数才执行
def saySorry():
    print("亲爱的,我错了,我能吃饭了吗?")
    time.sleep(1)

if __name__ == "__main__":
    for i in range(5):
        t = threading.Thread(target=saySorry)
        t.start() #启动线程,即让线程开始执行

说明:

  1. 可以明显看出使用了多线程并发的操作,花费时间要短很多
  2. 当调用start()时,才会真正的创建线程,并且开始执行

1.2 主线程会等待所有的子线程结束后才结束

#coding=utf-8
import threading
from time import sleep,ctime

def sing():
    for i in range(3):
        print("正在唱歌...%d" % i)
        sleep(1)

def dance():
    for i in range(3):
        print("正在跳舞...%d" % i)
        sleep(1)

if __name__ == '__main__':
    print('---开始---:%s' % ctime())

    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)

    t1.start()   # 创建了第1个子线程,主线程继续往下走,第1个子线程调用函数执行。
    
    t2.start()   # 创建了第2个子线程,主线程继续往下走,第2个子线程调用函数执行。

    sleep(5)   # 屏蔽此行代码,试试看,程序是否会立马结束?
    print('---结束---:%s' % ctime())    # ---结束---:Mon Aug  1 21:16:22 2022

1.3 查看线程数量 threading.enumerate()

#coding=utf-8
import threading
from time import sleep,ctime

def sing():
    for i in range(3):
        print("正在唱歌...%d"%i)
        sleep(1)

def dance():
    for i in range(3):
        print("正在跳舞...%d"%i)
        sleep(1)

if __name__ == '__main__':
    print('---开始---:%s' % ctime())

    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)

    t1.start()  
    t2.start()

    while True:
        length = len(threading.enumerate())  # 返回值threading.enumerate()列表有几个元素,就有几个线程
        print('当前运行的线程数为:%d' % length)
        if length<=1:  # 只剩一个的时候,一定是主线程,执行完毕退出
            break
        sleep(0.5)
        
# threading.enumerate()  列表中有3个元组      
# [<_MainThread(MainThread, started 27000)>, <Thread(Thread-1, started 45768)>, <Thread(Thread-2, started 61320)>]

1.3.1 补充-拆包

names = ["aa", "bb", "cc"]
for temp in names:
    print(temp)
结果:
aa
bb
cc


names = ["aa", "bb", "cc"]
for temp in enumerate(names):
    print(temp)
结果:
(0, 'aa')
(1, 'bb')
(2, 'cc')


names = ["aa", "bb", "cc"]
for i, name in enumerate(names):
    print(i, name)
结果:
0 aa
1 bb
2 cc

二、线程-类

2.1 线程执行代码的封装(类)

通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法

示例如下:

#coding=utf-8
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm "+self.name+' @ '+str(i)  # name属性中保存的是当前线程的名字
            print(msg)
            
            self.login()
            self.register()

    def login(self):
        print("这是登录···")

    def register(self):
        print("这是注册代码")


if __name__ == '__main__':
    t = MyThread()  # 创建一个实例对象,这个对象只能创建一个线程
    t.start()    # 一个线程只能执行一个函数,start会调用run方法


结果:
# I'm Thread-1 @ 0
# 这是登录···
# 这是注册代码
# I'm Thread-1 @ 1
# 这是登录···
# 这是注册代码
# I'm Thread-1 @ 2
# 这是登录···
# 这是注册代码

说明

  • python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。

2.2 线程的执行顺序

#coding=utf-8
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm "+self.name+' @ '+str(i)
            print(msg)
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()

执行结果:(运行的结果可能不一样,但是大体是一致的)

    I'm Thread-1 @ 0
    I'm Thread-2 @ 0
    I'm Thread-5 @ 0
    I'm Thread-3 @ 0
    I'm Thread-4 @ 0
    I'm Thread-3 @ 1
    I'm Thread-4 @ 1
    I'm Thread-5 @ 1
    I'm Thread-1 @ 1
    I'm Thread-2 @ 1
    I'm Thread-4 @ 2
    I'm Thread-5 @ 2
    I'm Thread-2 @ 2
    I'm Thread-1 @ 2
    I'm Thread-3 @ 2

说明:

  • 从代码和执行结果我们可以看出,多线程程序的执行顺序是不确定的。当执行到sleep语句时,线程将被阻塞(Blocked),到sleep结束后,线程进入就绪(Runnable)状态,等待调度。而线程调度将自行选择一个线程执行。
  • 上面的代码中只能保证每个线程都运行完整个run函数,但是线程的启动顺序、run函数中每次循环的执行顺序都不能确定。

2.3 总结

  1. 每个线程默认有一个名字,尽管上面的例子中没有指定线程对象的name,但是python会自动为线程指定一个名字。
  2. 当线程的run()方法结束时该线程完成。
  3. 无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。
目录
相关文章
|
14天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
1天前
|
开发者 Python
Python的os模块详解
Python的os模块详解
11 0
|
5天前
|
数据挖掘 API 数据安全/隐私保护
python请求模块requests如何添加代理ip
python请求模块requests如何添加代理ip
|
6天前
|
测试技术 Python
Python 有趣的模块之pynupt——通过pynput控制鼠标和键盘
Python 有趣的模块之pynupt——通过pynput控制鼠标和键盘
|
6天前
|
Serverless 开发者 Python
《Python 简易速速上手小册》第3章:Python 的函数和模块(2024 最新版)
《Python 简易速速上手小册》第3章:Python 的函数和模块(2024 最新版)
39 1
|
7天前
|
调度 Python
Python多线程、多进程与协程面试题解析
【4月更文挑战第14天】Python并发编程涉及多线程、多进程和协程。面试中,对这些概念的理解和应用是评估候选人的重要标准。本文介绍了它们的基础知识、常见问题和应对策略。多线程在同一进程中并发执行,多进程通过进程间通信实现并发,协程则使用`asyncio`进行轻量级线程控制。面试常遇到的问题包括并发并行混淆、GIL影响多线程性能、进程间通信不当和协程异步IO理解不清。要掌握并发模型,需明确其适用场景,理解GIL、进程间通信和协程调度机制。
27 0
|
8天前
|
Python
python学习-函数模块,数据结构,字符串和列表(下)
python学习-函数模块,数据结构,字符串和列表
49 0
|
10天前
|
Python
python学习14-模块与包
python学习14-模块与包
|
11天前
|
SQL 关系型数据库 数据库
Python中SQLite数据库操作详解:利用sqlite3模块
【4月更文挑战第13天】在Python编程中,SQLite数据库是一个轻量级的关系型数据库管理系统,它包含在一个单一的文件内,不需要一个单独的服务器进程或操作系统级别的配置。由于其简单易用和高效性,SQLite经常作为应用程序的本地数据库解决方案。Python的内置sqlite3模块提供了与SQLite数据库交互的接口,使得在Python中操作SQLite数据库变得非常容易。
|
16天前
|
索引 Python
「Python系列」Python operator模块、math模块
Python的`operator`模块提供了一系列内置的操作符函数,这些函数对应于Python语言中的内建操作符。使用`operator`模块可以使代码更加清晰和易读,同时也能提高性能,因为它通常比使用Python内建操作符更快。
27 0

热门文章

最新文章