前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【python实操】马上毕业了,你还不懂什么是守护线程、线程、进程?(附12306抢票程序-源代码)

【python实操】马上毕业了,你还不懂什么是守护线程、线程、进程?(附12306抢票程序-源代码)

作者头像
20岁爱吃必胜客
发布2023-03-30 14:58:34
4600
发布2023-03-30 14:58:34
举报
文章被收录于专栏:进步集进步集
  • 作者:20岁爱吃必胜客(坤制作人),近十年开发经验, 跨域学习者,目前于海外某世界知名高校就读计算机相关专业。
  • 荣誉:阿里云博客专家认证、腾讯开发者社区优质创作者,在CTF省赛校赛多次取得好成绩。
  • 跨领域学习,喜欢摄影、弹吉他、咏春拳。文章深入浅出、语言风趣;爱吃必胜客社区创立者,旨在“发现美 欣赏美

在这里插入图片描述
在这里插入图片描述

文章目录

⭐️前言

下面我们先回顾基础知识,分别是:

在这里插入图片描述
在这里插入图片描述

进程-process 线程-Treading 守护线程-Deamon Treading

🌟 进程-process

进程就是一个装线程的容器, 是线程的容器

进程就是一个个正在运行的独立软件

🌟 线程-Treading

又叫Light Weight Process LWP 轻量级进程 程序执行流的最小单元

线程组成:

代码语言:javascript
复制
线程id-----当前指令指针------寄存器集合---------堆栈

🌟 守护线程-Deamon Treading

☀️java中的应用

守护线程(Daemon Thread)是一种特殊的线程,其生命周期与 Java 虚拟机(JVM)的生命周期相同。当 JVM 中已不存在任何非守护线程时,虚拟机会自动退出,守护线程也会随之结束。因此,守护线程也被称为“服务线程”或“后台线程”

守护线程主要用于执行一些低优先级的任务,比如垃圾回收、内存管理、日志维护等工作。它通常不干扰其他线程的执行,当所有非守护线程执行结束后,它会被自动中断。

在 Java 中创建守护线程的方法是通过 Thread 类的 setDaemon() 方法,将线程设置为守护线程。当线程启动后,也可以使用 isDaemon() 方法来检查该线程是否为守护线程

需要注意的是,守护线程和非守护线程的区别在于它们的执行权限守护线程不能访问程序中的非守护线程或共享资源。因此,在使用守护线程时需要仔细考虑线程之间的依赖关系和共享资源的使用。

☀️python中的应用

Python中也有守护线程的概念,它与Java中的作用是相似的。在Python中,可以通过Thread类中的setDaemon方法来将线程设置为守护线程

在Python中,守护线程通常用于执行一些低优先级的任务或后台服务,例如监控另一个线程是否终止、自动保存数据等。当所有非守护线程结束时,守护线程也会自动结束,不会阻塞主进程的结束,这在一些长时间运行的程序中非常有用

需要注意的是,守护线程并不是万能的解决方案,它不能处理复杂的计算任务和涉及共享资源的并发问题。此外,在使用守护线程时需要仔细考虑线程之间的依赖关系和共享资源的使用,以避免数据竞争和死锁等问题。

下面是一个简单的例子,展示了如何在Python中创建守护线程:

代码语言:javascript
复制
import threading
import time

def print_time():
    for i in range(5):
        print("Current time:", time.ctime())
        time.sleep(1)

t = threading.Thread(target=print_time)
t.daemon = True # 将线程设置为守护线程
t.start()

print("Main process end.")

在上面的代码中,创建了一个名为print_time的函数,通过time模块打印当前时间,并在每次打印后等待1秒。然后创建了一个线程对象t,将print_time函数作为其目标函数,然后将线程设置为守护线程并启动。最后主进程打印一条结束信息。

⭐️多线程模块threading

在这里插入图片描述
在这里插入图片描述

现在用threading取代了thread模块。 Python中的threading模块提供了一种方便的方式来创建和管理线程。下面是使用threading模块创建和管理线程的示例代码:

代码语言:javascript
复制
import threading

# 定义一个线程执行的任务函数
def task():
    print("This is a task function.")
    
# 创建一个新线程
t = threading.Thread(target=task)

# 启动该线程
t.start()

# 等待该线程结束
t.join()

print("Main thread ends.")

在上面的代码中,首先定义了一个task()函数,用于表示线程执行的具体任务。然后通过threading.Thread()创建一个新的线程对象t,并将task函数作为其目标函数。最后启动该线程并等待其运行结束,然后主线程继续执行。

除了这个基本的线程创建和启动方式,threading模块还提供了一些方便的功能,例如:

  • threading.current_thread():返回当前线程对象;
  • threading.active_count():返回当前活跃的线程数;
  • threading.enumerate():返回当前所有活跃线程的列表;
  • threading.Lock():创建一个锁对象,用于保护共享资源的互斥操作;
  • threading.Event():创建一个事件对象,用于线程之间的通信和同步等。

🌟 使用锁来保护共享资源的访问

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面是一个例子,演示如何使用锁来保护共享资源的访问

代码语言:javascript
复制
import threading

# 定义一个共享变量
num = 0

# 创建一个锁对象
lock = threading.Lock()

# 定义一个线程执行的任务函数
def task():
    global num
    for i in range(1000000):
        lock.acquire()
        num += 1
        lock.release()

# 创建多个线程
threads = [threading.Thread(target=task) for i in range(10)]

# 启动这些线程
for t in threads:
    t.start()

# 等待这些线程结束
for t in threads:
    t.join()

print("Final result:", num)

在上面的代码中,首先定义了一个共享变量num,它的值将被多个线程共同更新。然后创建一个锁对象lock,用于保护num变量的访问。接下来定义一个task()函数。

⭐️queue模块

实现多生产者,多消费者队列 该技术是多线程安全共享数据的最佳选择技术之一。

⭐️多线程购买火车票的代码

以下是一个多线程购买火车票的代码示例:

代码语言:javascript
复制
import threading
import time

class Ticket:
    def __init__(self, name, quantity):
        self.name = name
        self.quantity = quantity
        self.lock = threading.Lock()
        
    def buy(self, num):
        self.lock.acquire()
        try:
            if self.quantity >= num:
                self.quantity -= num
                print(f"当前剩余车票:{self.quantity}")
                return True
            else:
                print("余票不足,购票失败")
                return False
        finally:
            self.lock.release()

def worker(name, ticket, num):
    while True:
        if ticket.buy(num):
            print(f"{name} 购买 {num} 张车票成功!")
            break
        else:
            print(f"{name} 正在尝试购买车票中...")
            time.sleep(1)

if __name__ == '__main__':
    t = Ticket("北京-上海", 10)
    threads = []
    for i in range(5):
        name = f"用户{i+1}"
        num = 2
        t1 = threading.Thread(target=worker, args=(name, t, num))
        threads.append(t1)
    for t in threads:
        t.start()
    for t in threads:
        t.join()

代码说明:

  1. Ticket 类表示火车票,包括票务名称和余票数量,以及一个锁对象用于线程同步。
  2. buy 方法用于购买车票,传入要购买的数量,如果余票足够则减少对应数量的余票,并返回 True,否则返回 False。
  3. worker 函数表示一个购票线程,不断尝试购买车票,如果成功则输出购买成功的信息,退出循环;否则等待 1 秒后重试。
  4. 在程序运行时创建 5 个购票线程,每个线程购买 2 张车票。线程启动后并发执行购票任务,直到所有线程购买成功为止。

注意:在实际开发中,购买车票需要连接网络、进行 IO 操作,并且可能会遇到一些异常情况,因此需要添加异常处理等相关代码来保证程序的稳定性和健壮性。

⭐️12306抢票程序-源代码

抢火车票需要模拟登陆、查询余票、提交订单等步骤,比较复杂,建议使用官方提供的API。以下是一个简单的模拟查询余票的Python代码示例。

代码语言:javascript
复制
import urllib.request
import json
import time

# 设置参数
fromStation = '北京'
toStation = '上海'
departureDate = '2022-01-01'

# 利用API查询余票
url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(departureDate, fromStation, toStation)
request = urllib.request.Request(url)
# 添加请求头
request.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3')
response = urllib.request.urlopen(request)
result = response.read().decode('utf-8')
data = json.loads(result)

# 解析结果
trains = data['data']['result']
for train in trains:
    trainList = train.split('|')
    if trainList[0] == '':  # 过滤无效车次
        continue
    if trainList[29] == 'Y':  # 判断是否有余票
        print('车次:{},余票数量:{}'.format(trainList[3], trainList[29]))

# 设置查询间隔
time.sleep(10)

需要注意的是,12306官方接口的调用频率有限制,需要合理控制查询间隔,防止被封IP。此外,需要获取验证码和自动提交订单等功能可以使用第三方库,比如PyAutoGUI。但是使用自动化脚本抢票有一定风险,建议谨慎操作。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • ⭐️前言
    • 🌟 进程-process
      • 🌟 线程-Treading
        • 🌟 守护线程-Deamon Treading
          • ☀️java中的应用
          • ☀️python中的应用
      • ⭐️多线程模块threading
        • 🌟 使用锁来保护共享资源的访问
        • ⭐️queue模块
        • ⭐️多线程购买火车票的代码
        • ⭐️12306抢票程序-源代码
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档