我这样回答多线程并发,面试官直接惊叹!

news2024/12/24 8:46:42

目录

前言:

1.单线程执行

2、多线程执行

3.守护线程

4.阻塞线程


前言:

多线程并发是一种处理任务的方式,它可以在同一时间内执行多个任务。多线程并发通常应用于需要同时处理多个任务或同时运行多个程序的情况下。

1.单线程执行

Python的内置模块提供了两个线程模块:threading 和thread。

    thread:是原生的

    threading:是扩展的

用法:

    变量 = threading.Thread(target = 执行函数)

    变量.strart()

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2020-06-08
# @Author : Carl_奕然

import threading
#自定义test函数
def test():
    print("test threading")
    
#创建一个单线程,来执行test()函数
t = threading.Thread(target= test)
t.start()

运行结果

test threading

2、多线程执行

单线程已经会使用,那么多线程还会远吗?
多线程只需要通过循环创建多个线程,并通过循环启动执行就可以了。
我们来看个例子,为了更直观,我把打印的内容修改成打印时间:

代码示例:

# -*- coding:utf-8 -*-
# @Time   : 2020-06-08
# @Author : Carl_奕然

import threading
from datetime import *

#自定义test函数
def test():
    now = datetime.now()  #获取当前时间
    print("打印多线程执行时间:",now)
#自定义thr()函数,来执行多线程
def thr():
    threads = []  #自定义一个空的数组,用来存放线程组
    for i in range(10):  #设置循环10次
        t = threading.Thread(target=test)
        threads.append(t)  #把创建的的线程t,装到threads 数组中
    #启动线程
    for t in threads: 
        t.start()
#执行thr()函数进行多并发
if __name__ == "__main__"   :
    thr()

运行结果

我们可以看到,我循环执行了10次,这时间相差的太小了,可以忽略不计。

如果,我设置1000次,10000次的话,如果还是这样写,是不是需要等待很长时间?服务器的压力会不会增加?资源消耗会不会增加?

那如何优化呢?

来看这个例子:

我们执行1000次并发,把这1000次拆成50个线程,每个线程循环20次,这样是不是就会快很多?

我们来看看执行效率

修改代码

# -*- coding:utf-8 -*-
# @Time   : 2020-06-08
# @Author : Carl_奕然

import threading
from datetime import *

#自定义test函数
def test():
    now = datetime.now()  #获取当前时间
    print("打印多线程执行时间:",now)
#设置50个线程
def looptest():
    for i in range(50):
        test()

#自定义thr()函数,来执行多线程
def thr():
    threads = []  #自定义一个空的数组,用来存放线程组
    for i in range(20):  #设置循环10次
        t = threading.Thread(target=test)
        threads.append(t)  #把创建的的线程t,装到threads 数组中
    #启动线程
    for t in threads:
        t.start()
#执行thr()函数进行多并发
if __name__ == "__main__"   :
    thr()

运行结果:

是不是快很多了。

3.守护线程

在了解守护线程之前,先来了解下主线程与子线程的区别。

主线程与子线程的区别:

每个线程都有一个唯一标示符,来区分线程中的主次关系的说法。

线程唯一标示符:Thread.CurrentThread.ManagedThreadID;

    ・UI界面和Main函数均为主线程。

    ・被Thread包含的“方法体”或者“委托”均为子线程。

    ・委托可以包含多个方法体,利用this.Invoke去执行。

    ・也可以定义多种方法体,放在Thread里面去执行。则此方法・体均为子线程。注意如果要修改UI界面的显示。则需要使用this.Invoke,否则会报异常。

    ・Main函数为主线程,id标示符与UI界面主线程相等。

对照上面的代码,main()就是主线程,thr()就是子线程。

>>即先启动main(),然后执行thr()启动子线程。

那么,什么是守护线程呢?

>>即当主线程执行完毕后,所有的子线程也被关闭(无论子线程是否执行完成)。默认是不设置守护线程的。

但是我们又为什么要用守护线程呢?

>>说的直接,就是为了防止死循环。

>>因为一个死循环如果不手动停止,我们都知道会一直的循环下去,直到资源耗尽。

那么守护线程的用法是什么呢?

>>setDaemon():默认是 False, 需要改成True才能启用。

代码示例:

# -*- coding:utf-8 -*-
# @Time   : 2020-06-08
# @Author : Carl_奕然

import threading
from datetime import *

#自定义test函数
def test():
    x=0
    while (x ==0):    #修改成死循环
        print(datetime.now())
#自定义thr()函数,来执行多线程
def thr():
    threads = []  #自定义一个空的数组,用来存放线程组
    for i in range(20):  #设置循环10次
        t = threading.Thread(target=test)
        threads.append(t)  #把创建的的线程t,装到threads 数组中
        t.setDaemon(True) # 设置守护线程
    #启动线程
    for t in threads:
        t.start()
#执行thr()函数进行多并发
if __name__ == "__main__"   :
    thr()
    print("守护线程功能启用,end")

运行结果:

4.阻塞线程

强制程序停止,除了运用守护线程,还可以用到 阻塞线程,

如果说前者是强硬派,那么后者就属于温柔派。

那么我们再来看看阻塞线程;

阻塞线程:通过子线程 join()方法来阻塞线程,

让主线程等待子线程完成之后再往下执行,

等主线程执行完毕后在挂你吧所有子线程。

代码示例:

# -*- coding:utf-8 -*-
# @Time   : 2020-06-08
# @Author : Carl_奕然

import threading
from datetime import *

def test():
    x =0
    while(x ==0):
        print(datetime.now())

def thr():
    threads = []
    for i in range(10):
        t = threading.Thread(target=test)
        threads.append(t)
        t.setDaemon(True)

    for t in  threads:
        t.start()
for t in threads:
    t.join()

if __name__ == "__main__":
    thr()
    print("阻塞线程功能启动,end")

这段代码,是不是让你有一种想喝(灭)水(火)的冲动??

那就对了,因为不能停止吗~ ~ ~ ~

那,这和什么都不设置不是一样???

莫着急,其实还是有一点区别的:

    >>什么都不设置的情况下主线程是执行完的,仅等待子线程执行完,所以会打印end信息

    >>而两个都设置的情况下,主线程会因为等待子线程结束而不往下执行,主线程无法执行完成,所以也就是无法关闭子线程,不会打印end信息

对于死循环这种情况,可以在join()设置timeout来控制

即,我们来设置个2秒钟,

    for t in threads:
        t.join(2)

但是你执行之后,会发现,为啥不是2秒停止,而是20秒才停止,是因为我们执行了10个线程, 而每个线程执行2秒,故10个线程timeout时间就是20秒。
是不是不太讲究,哎~~没办法,就顺了吧!!

    那么阻塞线程的意义是啥呢?
        >>阻塞线程的意义在于控制子线程与主线程的执行顺序!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/686884.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

便携式水污染检测设备可以分析多少项污水指标

便携式水污染检测设备可以分析多少项污水指标(以下只是一部分) 水质检测仪可检测范围 1、饮用水检测:生活用水(自来水)、(瓶、桶装)矿泉水、天然矿泉水等; 2、工业用水检测&#xf…

人机融合智能的现状与展望

本篇文章是博主在人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在学习摘录和笔记专…

【开源库剖析】Shadow v2.3.0 源码解析

作者:Stan_Z 一、框架介绍 Shadow是19年腾讯开源的自研Android插件化框架,经过线上亿级用户量检验。 Shadow不仅开源分享了插件技术的关键代码,还完整的分享了上线部署所需要的所有设计。 优点: 1)复用独立安装app源…

Python可视化库之Matplotlib详解及使用方法

Matplotlib是Python中最常用的可视化工具之一,可以非常方便地创建海量类型的2D图表和一些基本的3D图表。本文主要推荐一个学习使用Matplotlib的步骤。 基本前提 如果你除了本文之外没有任何基础,建议用以下几个步骤学习如何使用matplotlib: 学习基本的matplotlib术语,尤其是…

第二十二章Java一维数组的定义、赋值和初始化

当数组中每个元素都只带有一个下标时,这种数组就是“一维数组”。一维数组(one-dimensional array)实质上是一组相同类型数据的线性集合,是数组中最简单的一种数组。 数组是引用数据类型,引用数据类型在使用之前一定要…

Reactor的概念

一、Reactor的概念 ​ Reactor模式是一种事件驱动模式,由一个或多个并发输入源(input),一个消息分发处理器(Initiation Dispatcher),以及每个消息对应的处理器(Request Handler)构成…

Linux安装nodejs

一、下载包 https://registry.npmmirror.com/binary.html?pathnode/ 比如:10.9.0 https://registry.npmmirror.com/binary.html?pathnode/v10.9.0/ 按需下载 https://registry.npmmirror.com/-/binary/node/v10.9.0/node-v10.9.0-linux-x64.tar.gz 二、上传到…

使用Nginx+Lua实现自定义WAF(Web application firewall)

转载https://github.com/unixhot/waf WAF 使用NginxLua实现自定义WAF(Web application firewall) 功能列表: 支持IP白名单和黑名单功能,直接将黑名单的IP访问拒绝。 支持URL白名单,将不需要过滤的URL进行定义。 支持…

解析vcruntime140.dll文件,缺失了要怎么去修复?

在计算机的世界中,vcruntime140.dll是一个重要的动态链接库文件。然而,有时候这个文件可能会引发一系列问题,影响应用程序的正常运行。如果你缺少了vcruntime140.dll,那么你的程序就会打不开,今天我们一起来聊聊vcrunt…

408数据结构第四章

串 定义存储结构模式匹配 小题形式考,比较简单,拿两个题来练手就会了 定义 字符串简称串 由零个或多个字符组成的有限序列 S是串名n称为串的长度,n0称为空串 串中多个连续的字符组成的子序列称为该串的子串 串的逻辑结构和线性表极为相似&am…

ByteHouse+Apache Airflow:高效简化数据管理流程

Apache Airflow 与 ByteHouse 相结合,为管理和执行数据流程提供了强大而高效的解决方案。本文突出了使用 Apache Airflow 与 ByteHouse 的主要优势和特点,展示如何简化数据工作流程并推动业务成功。 主要优势 可扩展可靠的数据流程:Apache Ai…

使用MASA Stack+.Net 从零开始搭建IoT平台 第五章 使用时序库存储上行数据

目录 前言分析实施步骤时序库的安装解决playload没有时间戳问题代码编写 总结 前言 我们可以将设备上行数据存储到关系型数据库中,我们需要两张带有时间戳的表(最新数据表 和 历史数据表),历史数据表存储所有设备上报的数据&…

iptables详解

iptables简介 netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。 iptables 规则(rules)其实就是网络管理员预定义的条…

神通数据库X86架构适配DJANGO317指南

制作神通数据库镜像 1)、下载docker.io/centos:7.9.2009镜像,docker pull docker.io/centos:7.9.2009 2)、运行一个容器,docker run -itd --name shentong -p 2003:2003 --privilegedtrue --restartalways -v /sys/fs/cgroup:/sys/fs/cgrou…

万字详解JavaScript手写一个Promise

目录 前言Promise核心原理实现 Promise的使用分析MyPromise的实现在Promise中加入异步操作 实现then方法的多次调用 实现then的链式调用 then方法链式调用识别Promise对象自返回 捕获错误及 then 链式调用其他状态代码补充 捕获执行器错误捕获then中的报错错误与异步状态的链式…

硬盘设备出现“设备硬件出现致命错误,导致请求失败”怎么办?

当我们尝试访问或打开计算机上的硬盘设备,有时候会出现“设备硬件出现致命错误,导致请求失败”的错误提示,这该怎么办呢?下面我们就来了解一下。 出现“设备硬件出现致命错误,导致请求失败”错误的原因有哪些&#xff…

机器学习之SVM支持向量机

目录 经典SVM 软间隔SVM 核SVM SVM分类器应用于人脸识别 SVM优点 SVM缺点 经典SVM 支持向量机(Support Vector Machine,SVM)是一种二分类模型,其基本思想是在特征空间中找到一个最优的超平面,使得正负样本点到…

数据结构 队列(C语言实现)

绪论 任其事必图其效;欲责其效,必尽其方。——欧阳修;本篇文章主要写的是什么是队列、以及队列是由什么组成的和这些组成接口的代码实现过程。(大多细节的实现过程以注释的方式展示请注意查看) 话不多说安全带系好&…

Python3,关于请求重试,这次requests库给安排的明明白白。

requests库重试请求 1、引言2、requests库2.1 安装2.2 代码实例2.2.1 重试次数设置2.2.2 重试条件设置2.2.3 超时时间设置 3、总结 1、引言 小屌丝:鱼哥, 你看这是啥? 小鱼:我瞅瞅… 小屌丝:鱼哥,你这眼神…

【计算机视觉】Fast Segment Anything 安装步骤和示例代码解读(含源代码)

文章目录 一、导读二、安装步骤2.1 将存储库克隆到本地2.2 创建 conda 环境2.3 安装软件包2.4 安装 CLIP2.5 下载权重文件2.6 开始使用2.6.1 Everything mode2.6.2 Text prompt2.6.3 Box prompt (xywh)2.6.4 Points prompt 三、示例代码 一、导读 论文地址: https:…