首页 > 编程语言 >【进阶16】Python多线程实战案例

【进阶16】Python多线程实战案例

时间:2023-10-07 22:34:23浏览次数:40  
标签:__ 进阶 16 threading 线程 import 砖头 多线程 name

一、Python实现多线程的几种方式

_thread:模块提供了基本的线程和互斥锁支持;更底层的的线程管理实现模块 threading:threading模块则通过封装_thread,提供了更加全面的线程使用方法。 _thread案例:
# *coding:utf-8 *
#用_thread启动多个线程完成任务
import  _thread
import threading
#板砖的动作
import time
global brick_list
brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"]
def action():
    while True:
        if len(brick_list) ==0:
            break
        brick_list.pop()  #搬砖
        print(threading.currentThread(),"还剩%s" % (brick_list))
        time.sleep(0.1)

def main():
    #自己一个人搬
    # action()
    #请一个人
    # _thread.start_new_thread(action,())

    #请100个人,多个子进程运行
    for i in range(100):
        _thread.start_new_thread(action, ())
    time.sleep(10)



if __name__ == '__main__':
    main()
关键代码解释:
_thread.start_new_thread(action, ())
启动一个新的线程,执行action函数,  
threading案例:
# *coding:utf-8 *
import  _thread
import threading
#板砖的动作
import time
global brick_list
brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"]
def action():
    while True:
        if len(brick_list) ==0:
            break
        brick_list.pop()  #搬砖
        print(threading.currentThread(),"还剩%s" % (brick_list))
        time.sleep(0.1)

def main():
    #启动两个线程搬砖
    # t1=threading.Thread(target=action,args=())
    # t2=threading.Thread(target=action,args=())
    # t1.start()
    # t2.start()
    #启动100个线程搬砖
    for i in range(100):
        temp=threading.Thread(target=action,name="thread"+ str(i),args=())
        temp.start()
    time.sleep(10)

if __name__ == '__main__':
    main()
关键代码解释:
threading.Thread(target=action,name="thread1", args=())
创建一个线程,这个线程默认没有启动,需要继续调用start()来启动
例如:threading.Thread(target=action,name="thread1", args=()).start()
其中,target用要执行的任务函数,name是线程名,args是传递给执行的任务函数值

二、Threading多线程编程

2.1线程阻塞

Thread().join()
作用:阻塞主线程的运行,让主线程等待所有子线程运行结束之后,再继续运行
# *coding:utf-8 *
import  _thread
import threading
#板砖的动作
import time
global brick_list
brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"]
def action():
    while True:
        if len(brick_list) ==0:
            break
        brick_list.pop()  #搬砖
        print(threading.currentThread(),"还剩%s" % (brick_list))
        time.sleep(0.1)

def main():

    t1=threading.Thread(target=action,name="1号码农",args=(),daemon=True)   #daemon=True为守护进程,当主线程结束也会随之结束
    t1.start()
    t1.join()   #阻塞主线程


if __name__ == '__main__':
    main()

2.2 守护线程和非守护线程

获取Thread对象后,通过Thread对象中__init__方法中的daemon参数来设置守护线程和非守护线程,默认是非守护线程。 守护线程:其他线程都运行结束后,守护线程立即结束 非守护线程:无论其他线程有没有运行结束,本线程都必须正常运行结束后才会结束。
import threading
import time
from  time import sleep

def action(max):
    for i in range(max):
        print(threading.currentThread().name+"{}次循环\n".format(i))
    time.sleep(1)


def main():

    t = threading.Thread(target=action, args=(10000,), name='后台线程')
    t.daemon = True     #设置为守护线程
    # 启动后台线程
    t.start()
    for i in range(10):
        print(threading.current_thread().name+"主线程循环了{}次".format(i))
    print("主线程运行结束了")


if __name__ == '__main__':
    main()
2.3 线程锁(Lock)和信号量 线程锁(Lock): 为了防止线程与线程之间资源共享导致的线程安全问题,我们可以对访 问的资源加上锁,这个锁就是线程锁。 信号量:信号量是指控制有多少个线程可以访问的相同资源   2.3.1线程锁案例: Lock对象方法: acquire()   获取锁 release()  释放锁
import threading
from time import sleep
result = 0

#获取锁对象
lock=threading.Lock()
def add():
    global result
    lock.acquire()  #加锁
    for i in range(1000000):
        result = result + 1
    lock.release()  #解锁
    print("%s 的resul的结果为:%s" % (threading.current_thread().name,result))
def main():
     thread_list = []
     for i in range(3):
         thread_list.append(threading.Thread(target=add, name="t" + str(i))) # 初始化3个线程,
     #并把线程对象添加到thread_list中
     for i in range(3):
         thread_list[i].start() # 启动thread_list中的3个线程
if __name__ == '__main__':
 main()
2.3.2信号量案例:
import threading,time
semaphore=threading.Semaphore(500) #只允许500个人进入地铁站,执行运输任务

def action(counts):
    print("{}乘客来到地铁站".format(counts))
    semaphore.acquire()  # 获得信号量:信号量减一
    print("{}乘客已进站".format(counts))
    time.sleep(10)
    semaphore.release() #释放信号量:信号量加一
    print("{}乘客已出站".format(counts))

def main():
 for i in range(10000):
    t = threading.Thread(target=action, args=(i,))
    t.start()
if __name__ == '__main__':
 main()

三、队列和线程池  

1、队列用法:

from queue import Queue
#创建队列
q = Queue(maxsize=10)
队列常见操作方法:
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列
发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作 

案例:

import random
import threading
from queue import Queue
import time

q=Queue(10) #启动一个队列大小是10,能放10个菜
food_menu = ["佛跳墙", "红烧狮子头", "东坡肉", "蚂蚁 上树", "鱼香肉丝", "麻婆豆腐", "鱼子酱", "意大利面", "土豆丝炒肉", "银耳羹", "窝窝头", "糖醋排骨"]

def make_lunch():
    """服务端"""
    print("开始做菜")
    while True:
        if q.full():  #队列满了
            print("菜做好了")
            q.join()  #等待食客吃饭
        food_number=random.randint(0,len(food_menu)-1)
        q.put(food_menu[food_number])  # 写入队列
        print("做了:", food_menu[food_number])
        time.sleep(0.5)

def ear_lunch():

    time.sleep(10) # 等才做好了再开始吃
    while True:
        if q.empty():  #队列消息为空
            print("吃完了再来一顿")
            time.sleep(10)
        else:
            food_name=q.get() #获取队列消息
            print("吃了",food_name)
            q.task_done()
def main():
    #定义两个消息队列,并开启服务
    cooker=threading.Thread(target=make_lunch,args=(),name="cooker")
    eater=threading.Thread(target=ear_lunch,args=(),name="cooker")
    cooker.start()
    eater.start()


if __name__ == '__main__':
    main()

2、线程池:

顾名思义就是存放线程的池子,线程池可以控制线程的启动数量,从而达到节省系统资源的目的 作用:可以控制要启动的线程数量。 线程池与信号量Semaphore的区别:   线程池控制的是线程数量,而信号量控制的是并发数量。   超过信号量规定数量的线程,已经被启动了,只是状态是挂起。而线程池中,超过了线   程池规定数量的线程,还没有启动,只能等待启动。

使用方式:

threadpool库是第三方的库,所以必须要进行安装

#线程池案例
import  threading
import threadpool
import time
brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"]

def action(brick):
    print(threading.currentThread().name+"搬出了: ",brick)
    time.sleep(0.2)

def main():
    tp=threadpool.ThreadPool(5)  #设置5个线程
    requests=threadpool.makeRequests(action,brick_list)
    for req in requests: tp.putRequest(req)
    tp.wait()

if __name__ == '__main__':
    main()

四、tomorrow库:多线程并发测试库

pip install tomorrow 具体案例:

#使用tomorrow来完成“听歌、聊天、吃饭”三件事儿
import time
from random import random

from tomorrow import threads
import threading
@threads(10) # 最多开启10个线程完成任务
def task( task_name):
    print( threading.current_thread().name +"正在:", task_name)
if __name__ == '__main__':
 task_name_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"]

 for i in range(0,len(task_name_list)-1):
    task(task_name_list[i])
    time.sleep(0.2)

  

  

  

  

  

  

  

  

  

标签:__,进阶,16,threading,线程,import,砖头,多线程,name
From: https://www.cnblogs.com/xfbk/p/17747596.html

相关文章

  • 2023-2024-1 20231416 《计算机基础与程序设计》第二周学习总结
    计算机科学概论:  计算系统由硬件 软件和数据组成 是一种动态实体 动态即代表具有一定的灵活度 而实体代表其拥有一定的份量 而计算系统的分层也如同洋葱一般层层覆盖 信息隐藏和抽象两个概念也拥有很高的相似度 只不过抽象更注重于外部 信息隐藏更注重程序内部 计算机......
  • 39-16
    两个整数序列存放在单链表A,B中,设计一个算法,判断B是否是A的连续子序列算法思想类似于朴素匹配算法。遇到不匹配的,A需要记录与B开始匹配的位置(pre指针的作用),从该位置的下一个结点开始匹配,B从头开始匹配。#include<stdio.h>#include<stdlib.h>typedefstructnode{int......
  • 多线程,实现Callable接口
    这里改变了之前Thread和Runnable接口的下载网络图片的代码是要下载器类的,下面并没有写出来一、实现Callable接口,重写call()方法  是需要返回值的      好处:可以设置返回值和可以抛出异常 二、与Thread和Runnable接口不一样的地方,是需要四部来开启线程的, Exe......
  • springboot -- 整合 sharding-jdbc 读写分离+分库分表配置(进阶)
    sharding-jdbc说明:1、分库分表不能中途更改,取模算法的id会出错2、不支持特殊sql,包括去重,子sql,聚合等3、查询会给所有表发查询sql,带上分库,分表的字段的查询只发一条,4、查询数据要注意使用,尽量带上分库或分表字段来查询,避免多表查询sql过多取模算法假设2个表,test_0,test_1,分......
  • 多线程抢票,并发问题
    Tread类中:currentThread().getName()可以拿到自己的名字sleep() 模拟延时 一、一样的创建一个线程类来实现Runnable接口并且重写run方法 这里定义了Num来代表票数 run方法来实现抢票 如果票没了就break退出循环并且运用了Thread类中的两个方法开头有介绍二、实......
  • ThbinBook16+ Win10 蓝屏崩溃的解决思路
    背景近日,手头的联想笔记本频繁蓝屏重启,严重时一天三次,持续了近一周。错误代码基本均为:DRIVER_IRQL_NOT_LESS_OR_EQUAL​‍笔记本型号:ThinkBook16G4+ARA(21D1)操作系统:Win10排障思路重装驱动首先google和百度检索了一番错误代码,基本都指向驱动问题。‍上官网重新下载......
  • 学习Runnable接口来实现多线程
    1、先创建一个线程类来实现Runable接口 2、跟Thread类的一样照样调用FileUtils文件工具类创建下载器 3、对下载器的形参在线程类中创建属性,用构造方法对属性赋值,并且重写run方法,run方法中实例化下载器 4、实例化Runnable接口并且调用start方法 这里Runnable接口和T......
  • ThbinBook16+ Win10 蓝屏崩溃的解决思路
    背景近日,手头的联想笔记本频繁蓝屏重启,严重时一天三次,持续了近一周。错误代码基本均为:DRIVER_IRQL_NOT_LESS_OR_EQUAL​‍笔记本型号:ThinkBook16G4+ARA(21D1)操作系统:Win10排障思路重装驱动首先google和百度检索了一番错误代码,基本都指向驱动问题。‍上官网重新下载......
  • Ynoi2012 NOIP2016 人生巅峰
    Day\(\text{XXX}\)。注意到修改是易于复合的立方操作,而且值域非常小,所以可以直接\(O(v\logm)\)预处理出对每个\(i\in[0,v)\)操作了\(2^{j}\lem\)次的结果,维护出每一位被修改了多少次,查询某一位的值直接倍增\(O(\logm)\)即可。然后这个限制很弱,因为如果区间内有重复......
  • 一个多线程任务流程控制
    importthreadingclassQue_test:def__init__(self):#创建条件变量和计数器self.cv=threading.Condition()self.counter=1deffirst(self):withself.cv:print('first')self.counter+=1......