【Python使用】嘿马python高级进阶全体系教程第6篇:My Awesome Book,线程执行带有参数的任务【附代码文档】

40 阅读1分钟

🏆🏆🏆教程全知识点简介:1.静态Web服务器涵盖固定页面数据返回、命令行启动动态端口绑定。2. Python高级特性包括闭包变量修改、装饰器(定义、语法糖、执行时间统计)、property属性、with语句和上下文管理器、深拷贝和浅拷贝。3. 正则表达式涉及多字符匹配(*、{m,n})、开头结尾匹配(^$)、字符排除匹配、分组匹配。4. 操作系统基础包括操作系统概念、虚拟机软件、Ubuntu系统、Linux内核及发行版。5. Linux命令系统涵盖目录查看、路径操作、文件操作(ls、mkdir、rm、cp、mv)、重定向、文件内容查看、链接、压缩解压缩(tar、zip)。6. 系统管理包括文件权限(chmod)、用户权限(whoami、passwd)、用户创建、编辑器vim、软件安装卸载。7. 并发编程涵盖多任务概念、进程(进程编号获取、参数传递)、线程(执行特性、共享变量、死锁处理)、进程线程对比、协程(概念、优点、gevent)。8. 网络编程包括端口概念、TCP协议特点、socket使用、TCP开发流程、客户端服务端开发。9. HTTP协议涉及浏览器服务器通信、URL组成、开发者工具使用。


📚📚👉👉👉   gitee.com/yinuo112/Ba… 🍅🍅


🎯🎯🎯全教程总章节


🚀🚀🚀本篇主要内容

This file file serves as your book's preface, a great place to describe your book's content and ideas.

线程执行带有参数的任务

学习目标

  • 能够写出线程执行带有参数的任务

1. 线程执行带有参数的任务的介绍

前面我们使用线程执行的任务是没有参数的,假如我们使用线程执行的任务带有参数,如何给函数传参呢?

Thread类执行任务并给任务传参数有两种方式:

  • args 表示以元组的方式给执行任务传参

  • kwargs 表示以字典方式给执行任务传参

2. args参数的使用

示例代码:

import threading
import time


  
  
# 带有参数的任务
  
  
def task(count):
    for i in range(count):
        print("任务执行中..")
        time.sleep(0.2)
    else:
        print("任务执行完成")


if __name__ == '__main__':
    # 创建子线程
    # args: 以元组的方式给任务传入参数
    sub_thread = threading.Thread(target=task, args=(5,))
    sub_thread.start()

执行结果:

任务执行中..
任务执行中..
任务执行中..
任务执行中..
任务执行中..
任务执行完成

Python-dotenv 文档

3. kwargs参数的使用

示例代码:

import threading
import time


  
  
# 带有参数的任务
  
  
def task(count):
    for i in range(count):
        print("任务执行中..")
        time.sleep(0.2)
    else:
        print("任务执行完成")


if __name__ == '__main__':
    # 创建子线程
    # kwargs: 表示以字典方式传入参数
    sub_thread = threading.Thread(target=task, kwargs={"count": 3})
    sub_thread.start()

执行结果:

任务执行中..
任务执行中..
任务执行中..
任务执行完成

4. 小结

  • 线程执行任务并传参有两种方式:

    • 元组方式传参(args) :元组方式传参一定要和参数的顺序保持一致。
    • 字典方式传参(kwargs):字典方式传参字典中的key一定要和参数名保持一致。

线程的注意点

学习目标

  • 能够说出线程的注意点

1. 线程的注意点介绍

  1. 线程之间执行是无序的

  2. 主线程会等待所有的子线程执行结束再结束

  3. 线程之间共享全局变量

  4. 线程之间共享全局变量数据出现错误问题

2. 线程之间执行是无序的

Flask 官方文档

import threading
import time


def task():
    time.sleep(1)
    print("当前线程:", threading.current_thread().name)


if __name__ == '__main__':

   for _ in range(5):
       sub_thread = threading.Thread(target=task)
       sub_thread.start()

执行结果:

当前线程: Thread-1
当前线程: Thread-2
当前线程: Thread-4
当前线程: Thread-5
当前线程: Thread-3

说明:

  • 线程之间执行是无序的,它是由cpu调度决定的 ,cpu调度哪个线程,哪个线程就先执行,没有调度的线程不能执行。

  • 进程之间执行也是无序的,它是由操作系统调度决定的,操作系统调度哪个进程,哪个进程就先执行,没有调度的进程不能执行。

3. 主线程会等待所有的子线程执行结束再结束

假如我们现在创建一个子线程,这个子线程执行完大概需要2.5秒钟,现在让主线程执行1秒钟就退出程序,查看一下执行结果,示例代码如下:

datetime 文档

import threading
import time


  
  
# 测试主线程是否会等待子线程执行完成以后程序再退出
  
  
def show_info():
    for i in range(5):
        print("test:", i)
        time.sleep(0.5)


if __name__ == '__main__':
    sub_thread = threading.Thread(target=show_info)
    sub_thread.start()

    # 主线程延时1秒
    time.sleep(1)
    print("over")

执行结果:

test: 0
test: 1
over
test: 2
test: 3
test: 4

说明:

通过上面代码的执行结果,我们可以得知: 主线程会等待所有的子线程执行结束再结束

假如我们就让主线程执行1秒钟,子线程就销毁不再执行,那怎么办呢?

  • 我们可以设置守护主线程

守护主线程:

  • 守护主线程就是主线程退出子线程销毁不再执行

设置守护主线程有两种方式:

  1. threading.Thread(target=show_info, daemon=True)
  2. 线程对象.setDaemon(True)

设置守护主线程的示例代码:

phonenumbers 文档

import threading
import time


  
  
# 测试主线程是否会等待子线程执行完成以后程序再退出
  
  
def show_info():
    for i in range(5):
        print("test:", i)
        time.sleep(0.5)


if __name__ == '__main__':
    # 创建子线程守护主线程 
    # daemon=True 守护主线程
    # 守护主线程方式1
    sub_thread = threading.Thread(target=show_info, daemon=True)
    # 设置成为守护主线程,主线程退出后子线程直接销毁不再执行子线程的代码
    # 守护主线程方式2
    # sub_thread.setDaemon(True)
    sub_thread.start()

    # 主线程延时1秒
    time.sleep(1)
    print("over")

Quart 文档

执行结果:

test: 0
test: 1
over

3. 线程之间共享全局变量

需求:

  1. 定义一个列表类型的全局变量
  2. 创建两个子线程分别执行向全局变量添加数据的任务和向全局变量读取数据的任务
  3. 查看线程之间是否共享全局变量数据

structlog 文档

import threading
import time


  
  
# 定义全局变量
  
  
my_list = list()

  
  
# 写入数据任务
  
  
def write_data():
    for i in range(5):
        my_list.append(i)
        time.sleep(0.1)
    print("write_data:", my_list)


  
  
# 读取数据任务
  
  
def read_data():
    print("read_data:", my_list)


if __name__ == '__main__':
    # 创建写入数据的线程
    write_thread = threading.Thread(target=write_data)
    # 创建读取数据的线程
    read_thread = threading.Thread(target=read_data)

    write_thread.start()
    # 延时
    # time.sleep(1)
    # 主线程等待写入线程执行完成以后代码在继续往下执行
    write_thread.join()
    print("开始读取数据啦")
    read_thread.start()

执行结果:

write_data: [0, 1, 2, 3, 4]
开始读取数据啦
read_data: [0, 1, 2, 3, 4]

4. 线程之间共享全局变量数据出现错误问题

需求:

  1. 定义两个函数,实现循环100万次,每循环一次给全局变量加1
  2. 创建两个子线程执行对应的两个函数,查看计算后的结果
import threading

  
  
# 定义全局变量
  
  
g_num = 0


  
  
# 循环一次给全局变量加1
  
  
def sum_num1():
    for i in range(1000000):
        global g_num
        g_nu