多线程使用详解---Threading

 

一 . 线程的概念

1. 简介


首先说下,python刚出来的时候,那个时候的计算机都是单核的
简单来说当时一次只能完成一个任务,当有多个任务时候不知道先执行哪个,GIL加了全局解释器锁,这样保证了开启多线程任务时,每次也只能一个任务执行,在执行过程中是随机切换线程任务,约200字节码随机切换!

2. 概念

线程是系统进行资源调度的最小单位,它属于进程,每一个进程中都会有一个线程,由于线程操作是单进程的,所以线程之间可以共享内存变量,互相通信非常方便,它的系统开销比进程小,它是线程之间由于共享内存,会互相影响,如果一个线程僵死会影响其他线程,隔离性和稳定性不如进程,同时,线程并不安全,如果对同一个对象进行操作,需要手动加锁,另外从性能上讲,多线程会触发python的全局解释器锁,导致同一时间点只会有一个线程运行的交替运行模式。

3.使用场景

线程适用于io密集型任务,所谓io密集型任务就是大量的硬盘读写操作或者网络tcp通信的任务,一般就是爬虫和数据库操作,文件操作非常频繁的任务。

4.操作

线程使用的是Threading库 ,往往是先声明线程实例,里面可以传入消费方法名称和不定长参数args,然后将实例放入指定线程数的容器中(list),通过循环或者列表推导式,使用start方法开启线程,join方法阻塞主线程。

import time
import threading

from utils import AuditQueue
import asyncio


def job(num):
    # 获取商户uid
    uid= asyncio.run(AuditQueue().bout())

    if uid:
        print(uid)
    else:
        print("队列为空")


    print("任务-{}执行完毕".format(num))


def start_thread(num):
    # 创建线程对象
    threads = [threading.Thread(target=job, args=(x,)) for x in range(num)]

    # 执行多线程任务
    for t in threads:
        t.start()

    for t in threads:
        t.join()


if __name__ == '__main__':
    start = time.time()

    # 审核员数量为3
    start_thread(3)
    end_time = time.time() - start
    print(end_time)

二. 线程相关问题

1.线程锁:

若是使用多线程对整型数据操作,多线程在随机切换的情况下,值是无法恒定的,这时候需要加上一把锁,即线程锁

在多线程的情况下,会出现资源抢占,抢占锁的问题,若不释放锁,会造成死锁问题

# 线程锁
import threading


balance = 0

def change(n):

    global balance


    if lock.acquire():
        try:

            for x in range(1000000):
                balance = balance + n
                balance = balance - n
        # 理论上最终一定会执行(出错误也要释放这把锁)  exit(-1)打断点就不一定执行  仍然造成死锁
        finally:

            # 释放锁
            lock.release()


if __name__ == '__main__':

    threads = [threading.Thread(target=change,args=(x,)) for x in range(6)]

    lock = threading.Lock()

    [t.start() for t in threads]
    [t.join() for t in threads]

    print(balance)

2.线程池:


系统启动一个新线程的成本是比较高的,因为它涉及与操作系统的交互。使用线程池能够存放大量的线程,可以很好的提升性能。

线程池在系统启动时创建大量的空线程,程序只需将一个函数提交给线程池,线程池会启动最后一个线程来执行函数,执行完成,该线程会重新回到线程池中排队,等待新的函数的到来,这样就省去了销毁线程和创建新线程的过程。

线程池还有一点好处就是能够有效的控制系统中并发线程的数量,防止大量并发线程启动,python解释器崩溃


import threading


# 线程池
class Pool:
    def __init__(self,num):

        self.num = num
        # 建立多线程
        self.threads = [self.make_connect(x) for x in range(num)]

    def make_connect(self,name):

        conn = "链接-{}".format(name)
        return conn

    # 获取链接
    def get_connect(self):
        return self.threads.pop()

    # 归还链接
    def return_connect(self,conn):
        self.threads.insert(0,conn)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值