"/>
侧边栏壁纸
博主头像
PySuper博主等级

千里之行,始于足下

  • 累计撰写 204 篇文章
  • 累计创建 14 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Python处理多任务(二) -- 线程

PySuper
2019-11-06 / 0 评论 / 0 点赞 / 18 阅读 / 8429 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

线程

什么是线程

  • 在程序运行过程中,执行程序代码的一个分支,每个运行的程序至少都有一个线程
  • 线程列表: threading.enumerate()
import threading
import time


def song(name, age):
    while True:
        print('song', name, age)
        time.sleep(1)

def dance():
    while True:
        print('dance')
        time.sleep(1)

def main():
    # child_thread = threading.Thread(target=dance)
    # child_thread.start()

    # 可以转换成:
    threading.Thread(target=dance).start()

    # 传参 ==>> args=() 传入的是一个元组
    threading.Thread(target=song, args=('小张', 14)).start()

    # 创建两个进程,并开启进程

if __name__ == '__main__':
    main()

注意点

  • 线程之间的执行是无序的
  • 主线程会等待所有的子线程结束后才结束
  • 子线程任务执行不完程序退出不了,解决办法设置子线程守护主线程
  • 守护主线程
    • 设置成为守护主线程,主线程退出后子线程直接销毁, 不再执行子线程的代码
    • daemon=True 守护主线程
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")

自定义线程

不能指定target,因为自定义线程里面的任务都统一在run方法里面执行

启动统一调用start方法(直接run, 不是使用子线程去执行任务)

import threading

# 自定义线程类
class MyThread(threading.Thread):
    # 通过构造方法取接收任务的参数
    def __init__(self, info1, info2):
        # 调用父类的构造方法
        super(MyThread, self).__init__()
        self.info1 = info1
        self.info2 = info2

    # 定义自定义线程相关的任务
    def test1(self):
        print(self.info1)

    def test2(self):
        print(self.info2)

    # 通过run方法执行相关任务
    def run(self):
        self.test1()
        self.test2()

# 创建自定义线程
my_thread = MyThread("测试1", "测试2")
# 启动
my_thread.start()

##共享全局变量

多线程共享全局变量,很方便在多个线程间共享数据

多线程同时操作全局变量(资源竞争), 导致数据可能出现错误

  • 线程同步: 保证同一时刻只能有一个线程去操作全局变量(变成单任务)
    • 线程等待(join)
    • 互斥锁
  • 同步: 就是协同步调,按预定的先后次序进行运行。
import threading

# 定义全局变量
g_num = 0

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

    print("sum1:", g_num)
    
# 循环1000000次每次给全局变量加1
def sum_num2():
    for i in range(1000000):
        global g_num
        g_num += 1
    print("sum2:", g_num)

if __name__ == '__main__':
    # 创建两个线程
    first_thread = threading.Thread(target=sum_num1)
    second_thread = threading.Thread(target=sum_num2)

    # 启动线程
    first_thread.start()
    # 主线程等待第一个线程执行完成以后代码再继续执行,让其执行第二个线程
    # 线程同步: 一个任务执行完成以后另外一个任务才能执行,同一个时刻只有一个任务在执行
    first_thread.join()
    # 启动线程
    second_thread.start()

互斥锁

  • 对共享数据进行锁定,保证同一时刻只能有一个线程去操作
    • 如果这个锁之前是没有上锁的,那么acquire不会堵塞
    • 如果在调用acquire对这个锁上锁之前,它已被其他线程上锁,则此时acquire会堵塞,直到这个锁被解锁为止
  • 能够保证多个线程访问共享数据不会出现资源竞争及数据错误
# 创建锁
mutex = threading.Lock()

# 锁定
mutex.acquire()

# 释放
mutex.release()

注意

  • 抢到锁的线程先执行,没有抢到锁的线程需要等待,等锁用完后需要释放,然后其它等待的线程再去抢这个锁,那个线程抢到那个线程再执行。
  • 具体那个线程抢到这个锁我们决定不了,是由cpu调度决定的

优缺点

  • 优点
    • 确保了某段关键代码只能由一个线程从头到尾完整地执行
  • 缺点
    • 多线程执行变成了包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
    • 锁使用不好就容易出现死锁情况

死锁

  • 一直等待对方释放锁的情景就是死锁
  • 死锁一旦发生就会造成应用的停止响应
  • 避免死锁:在合适的地方释放锁

Django DeleteView 源码解析

Django CreateView、UpdateView 源码解析

Django ContentTypes 框架

Linux 下升级 Python 版本

Django WebSocket (一):WebSocket 概念及原理

Django WebSocket (二):Channels 概念及原理

Django WebSocket (三):Channels + WebSocket 实现在线聊天

Python 对数器实现与使用

Django Redis 缓存优化

Django ORM优化 和 SQL优化

Python 应用部署

代理 IP 抓取及使用(自动重连)

使用 pandas、xlrd、xlwt 读写 Excel

cookiecutter 火速创建 Django项目

Ngrok 实现 内网穿透

蓝绿部署、滚动部署、金丝雀发布(灰度发布)、A/B测试

冒泡排序、选择排序、插入排序

递归分析、归并排序

Python 自定义比较器

经典快排、随机快排、Python代码实现

堆排序、Python实现堆排序

桶排序、计数排序、基数排序

Crontab + Celery 定时处理异步任务

Django 信号机制、消息框架

分布式文件系统 NFS 配置(Deepin)

Kubernetes | Pod

Kubernetes | 资源清单

Kubernetes | 资源控制器

Kubernetes | Service

Kubernetes | 存储

Kubernetes | 集群调度

Kubernetes | 安全

Python 项目代码规范

MySQL 数据库拆分

实践:Crontab、Celery 分布式 异步

MySQL 创建用户与权限管理

GitLab、Jenkins、Harbor 安装 | CentOS、Docker

Nginx 常用配置

JetBrains | PyCharm 链接 GitLab | GitHub

DevOps | Docker | Harbor 安装与配置 | 踩坑

DevOps | GitLab CI/CD | Runner | Pipline | gitlab-ci.yml

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区