首页 > 编程语言 >python 多任务之多线程

python 多任务之多线程

时间:2024-06-09 13:57:38浏览次数:30  
标签:__ thread python threading num 线程 print 多线程 多任务

多线程

线程是程序执行的最小单位,实际上进程只负责分配资源,而利用这些资源执行程序的是线程,也就是说进程是线程的容器,一个进程中最少有一个线程来负责执行程序,它可以与同属一个进程的其它线程共享进程所拥有的全部资源

 

为什么要选择线程,而不选择进程

进程:就像同时和两个人聊QQ,就需要打开两个QQ软件,会占用没必要的资源

线程:就像同时和两个人聊QQ,只需要打开两个窗口就可以了,也会节省很多资源

 

线程的创建步骤

1.导入所需要的线程模块
import threading

2.通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名)

3.启动线程
线程对象.start()

 

多线程的使用

import threading
import time

def eat():
    for i in range(5):
        print('正字吃饭=============')
        time.sleep(0.5)        # 等待0.5秒后再执行


def music():
    for i in range(5):
        print('正在唱歌=============')
        time.sleep(0.5)       # 等待0.5秒后再执行


if __name__ == '__main__':

    eat_thread = threading.Thread(target=eat,)
    music_thread = threading.Thread(target=music,)

    eat_thread.start()
    music_thread.start()

执行结果

9c37548225bf485e87a7074091b6ef7d.png

 

线程执行任务函数的传参

  • 元组方式传参:元组方式传参一定要和参数的顺序保持一致
  • 字典方式传参:字典方式传参字典中的key一定要和参数名保持一致
import threading
import time

def eat(num, name):
    for i in range(num):
        print(f'{name}正字吃饭=============')
        time.sleep(0.5)        # 等待0.5秒后再执行


def music(num, name):
    for i in range(num):
        print(f'{name}正在唱歌=============')
        time.sleep(0.5)       # 等待0.5秒后再执行


if __name__ == '__main__':

    eat_thread = threading.Thread(target=eat, args=(3, '张三'))
    music_thread = threading.Thread(target=music, kwargs={'num': 5, 'name': '李四'})

    eat_thread.start()
    music_thread.start()

执行结果

4b68f729761a49a087abf43ea2e986ca.png

 

守护主线程

主线程会等待所有的子线程执行结束后主线程再结束,但是也是可以主线程不等待子线程执行完成,可以设置守护主线程

两种方式

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

不设置守护主线程的情况下

import threading
import time

def eat():
    for i in range(10):
        print('正在吃饭==========')
        time.sleep(0.5)

if __name__ == '__main__':
    # 创建子线程
    eat_thread = threading.Thread(target=eat,)
    # 启动子线程
    eat_thread.start()
    time.sleep(2)
    print('主线程执行完毕========')

执行结果

f72bfe0294c24f8196ba8219d3992400.png

方式一守护主线程

import threading
import time

def eat():
    for i in range(10):
        print('正在吃饭==========')
        time.sleep(0.5)

if __name__ == '__main__':
    # 创建子线程
    eat_thread = threading.Thread(target=eat, daemon=True)
    # 启动子线程
    eat_thread.start()
    time.sleep(2)
    print('主线程执行完毕========')

执行结果

5bd2e2a5ba544ff3960d93a17fc2bc26.png

方式二守护主线程

import threading
import time

def eat():
    for i in range(10):
        print('正在吃饭==========')
        time.sleep(0.5)

if __name__ == '__main__':
    # 创建子线程
    eat_thread = threading.Thread(target=eat,)
    # 需要写在开启子线程前面
    eat_thread.setDaemon(True)
    # 启动子线程
    eat_thread.start()
    time.sleep(2)
    print('主线程执行完毕========')

执行结果

5a8827d6caf14c738de645239e8e8ef0.png

 

线程的执行顺序

一个进程里面,多个线程在执行,线程的执行是无序的,是由CPU调度决定某个线程先执行

获取当前线程的信息

1、通过current_thread方法获取线程对象的信息,例如被创建的顺序
current_thread_info = threading.current_thread()

print(current_thread_info)

import threading
import time

def thread_info():

    time.sleep(0.5)

    current_thread_info = threading.current_thread()
    print(current_thread_info)

if __name__ == '__main__':

    for i in range(5):
        sub_thread = threading.Thread(target=thread_info,)
        sub_thread.start()

执行结果

18399294b3cd4791b928890ec68e2e0b.png

 

线程间共享全局变量

多个线程都是在同一个进程中,多个线程使用的资源都是同一个进程中的资源,因此多线程间是共享全局变量

import time
import threading

def write_date():
    for i in range(3):
        my_list.append(i)
    print('这是子线程写入的表:', my_list)

def read_date():
    print('这是子线程读数据:', my_list)

my_list = []
if __name__ == '__main__':

    write_thread = threading.Thread(target=write_date)
    read_thread = threading.Thread(target=read_date)

    write_thread.start()
    time.sleep(1)
    read_thread.start()
    time.sleep(1)

    print('这是主线程读的数据:', my_list)

执行结果

b397a28e67364eb0ad84a5e5714bd36e.png

 

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

解决办法

  • 同步:就是协同步调,按预定的先后次序进行运行。比如现实生活中的对讲机,你说一句我说一句,不能一起说
  • 使用线程同步:也就是互斥锁,同一时刻只能有一个线程去操作全局变量

不使用的情况下

import threading

# 定义全局变量
num = 0

def sum_num1():
    for i in range(1000):
        global num
        num += 1
    print('num1:', num)

def sum_num2():
    for i in range(1000):
        global num
        num += 1
    print('num2:', num)

if __name__ == '__main__':

    sum1 = threading.Thread(target=sum_num1,)
    sum2 = threading.Thread(target=sum_num2,)

    sum1.start()
    sum2.start()

执行结果

551170087d1d49cfb3ec417c2b8cd514.png

把num加大

import threading

# 定义全局变量
num = 0

def sum_num1():
    for i in range(1000000):      # 多加了几个0
        global num
        num += 1
    print('num1:', num)

def sum_num2():
    for i in range(1000000):       # 多加了几个0
        global num
        num += 1
    print('num2:', num)

if __name__ == '__main__':

    sum1 = threading.Thread(target=sum_num1, )
    sum2 = threading.Thread(target=sum_num2, )

    sum1.start()
    sum2.start()

执行结果

9d36e411c39e45bca5b6b981aa49e3de.png

 

互斥锁的使用

对共享数据进行锁定,保证同一时刻只有一个线程去操作

互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到的线程进行等候,等锁使用完释放后,其它等待的线程再去抢这个锁

使用

1、创建互斥锁
mutex  = threading.Lock()
2、上锁
mutex .acquire()
3、释放锁
mutex .release()

import time
import threading

# 定义全局变量
num = 0

def sum_num1():
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global num
        num += 1
    print('num1:', num)
    # 释放锁
    mutex.release()

def sum_num2():
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global num
        num += 1
    print('num2:', num)
    # 释放锁
    mutex.release()

if __name__ == '__main__':
    # 创建锁
    mutex = threading.Lock()
    # 创建子线程
    sum1 = threading.Thread(target=sum_num1, )
    sum2 = threading.Thread(target=sum_num2, )
    # 启动子线程
    sum1.start()
    sum2.start()

    time.sleep(5)
    print(num)

执行结果

 09a331ddb60b4268b08ce07325bd20b0.png

死锁

一直等待对方释放锁的情况就是死锁,死锁会造成程序的停止响应,不能再处理其他任务

产生死锁的原因:没有及时或者在正确的位置释放锁

 

 

标签:__,thread,python,threading,num,线程,print,多线程,多任务
From: https://blog.csdn.net/qq_64993426/article/details/139468473

相关文章

  • python - pandas常用计算函数
    文中所用数据集有需要的可以私聊我获取学习目标 知道排序函数nlargest、nsmallest和sort_values的用法知道Pandas中求和、计数、相关性值、最小、最大、平均数、标准偏差、分位数的函数使用1排序函数导包并加载数据集importpandasaspd​#加载csv数据,返回df......
  • 超详解——python数字和运算——小白篇
    目录1.位运算2.常用内置函数/模块math模块:random模块:decimal模块:3.内置函数:总结:1.位运算位运算是对整数在内存中的二进制表示进行操作。Python支持以下常见的位运算符:按位与(&):两个二进制数对应位都为1时,结果的该位才为1。按位或(|):两个二进制数对应位有一个为1,结果......
  • 运筹学练习Python精解——指派问题
    练习8分配甲、乙、丙、丁4个人去完成A、B、C、D、E5项任务,每个人完成各项任务的时间见下表。由于任务数多于人数,故考虑:(1)任务E必须完成,其他4项中可任选3项完成;(2)其中有一人完成两项,其他每人完成一项。试分别确定最优分配方案,使完成任务的总时间为最少。人员\任务AB......
  • 【四种语言一网打尽(C\C++\Python\Golang)】L1-005 考试座位号
    L1-005考试座位号每个PAT考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着......
  • 【机器学习基础】Python编程07:五个实用练习题的解析与总结
    Python是一种广泛使用的高级编程语言,它在机器学习领域中的重要性主要体现在以下几个方面:简洁易学:Python语法简洁清晰,易于学习,使得初学者能够快速上手机器学习项目。丰富的库支持:Python拥有大量的机器学习库,如scikit-learn、TensorFlow、Keras和PyTorch等,这些库提供了......
  • 【机器学习基础】Python编程08:五个实用练习题的解析与总结
    Python是一种广泛使用的高级编程语言,它在机器学习领域中的重要性主要体现在以下几个方面:简洁易学:Python语法简洁清晰,易于学习,使得初学者能够快速上手机器学习项目。丰富的库支持:Python拥有大量的机器学习库,如scikit-learn、TensorFlow、Keras和PyTorch等,这些库提供了......
  • Plotly : 超好用的Python可视化工具
    文章目录安装:开始你的Plotly之旅基本折线图:简单却强大的起点带颜色的散点图:数据的多彩世界三维曲面图:探索数据的深度气泡图:让世界看到你的数据小提琴图:数据分布的优雅展现旭日图:分层数据的直观展示热力图:变量之间关系的直观展示雷达图:多维数据的全面展示三维散点图:空间......
  • Python+pytest+jenkins 多插件 pdf电子书目录
    第1章pytest入门11.1资源获取 41.2运行Pytest 51.3运行单个测试用例 101.4使用命令行选项 10--collect-only选项 11-k选项 11-m选项 12-x选项 13--maxfail=num 15-s与--capture=method 16-lf(--lastfailed)选项 16--ff(--failed-first)选项 17......
  • Python 运算符重载
    在Python中,运算符重载是一种允许你定义或修改内置运算符(例如+,-,*,/等)在自定义类中的行为的技术。通过重载运算符,你可以使这些运算符对自定义对象执行特定的操作。运算符重载是通过在类中定义特殊方法(也称为魔法方法)来实现的,这些方法通常以双下划线开头和结尾。以下是一些常......
  • Python_编程基础
    Python_编程基础Python编程基础0、简单介绍解释型语言:一边编译一边运行,不需要进行编译,运行效率比较低解释器JavaScript-浏览器python.exephp.exe编译型语言:运行前需要进行编译,运行效率比较高C.c->.exe组合:anaconda+pycharm、python+pycharm/sublime/geany/vs......