C++密码管理器

news2024/11/13 10:59:20

先问一句

最近有几个关注我的原力等级为0或-1,文章全是转载,转载时间基本都在2021年,而且关注了很多人,这些是僵尸粉吗?

文末有投票,麻烦参与一下谢谢


实现功能列表

暂时还没做加密功能 打算用openssl/aes.h 实现 源码在最后面

1. 添加第三方账号密码

  • 输入数据
    • ID:唯一标识账号的编号。
    • 平台:第三方平台的名称(如Facebook、Twitter等)。
    • 账号:用于登录的用户名或电子邮件。
    • 密码:用于登录的密码。
  • 功能
    • 检查ID是否唯一,避免重复添加。
    • 检查密码的安全性(包括强度等级和破解时间估算)。
    • 将账号信息保存到数据文件 data.txt

2. 删除第三方账号密码

  • 输入数据
    • ID:要删除的账号的唯一编号。
  • 功能
    • 根据ID从数据中删除相应的账号信息。
    • 更新 data.txt 文件,删除对应的记录。

3. 查找第三方账号密码

  • 输入数据
    • 平台名称:要查找的第三方平台的名称。
  • 功能
    • 根据平台名称查找所有相关的账号记录。
    • 显示匹配的账号信息(包括ID、平台、账号和密码)。

4. 修改第三方账号密码

  • 输入数据
    • ID:要修改的账号的唯一编号。
  • 功能
    • 根据ID找到并修改对应的账号信息(平台、账号和密码)。
    • 更新 data.txt 文件,保存修改后的记录。

5. 修改管理器密码

  • 输入数据
    • 当前密码:需要验证的旧管理器密码。
    • 新密码:设置的新管理器密码。
  • 功能
    • 验证当前密码是否正确。
    • 更新管理器密码,并保存到文件 password.dat

6. 显示所有弱密码

  • 功能
    • 检查所有账号密码的安全性。
    • 显示所有被标记为“弱”的密码(即不符合安全标准的密码)。

7. 显示重复密码

  • 功能
    • 查找并显示在相同平台上使用的重复密码。
    • 列出所有平台及其对应的重复密码信息。

8. 退出程序

  • 功能
    • 退出密码管理器程序。

部分实现方法

1.密码安全性检测

1.1 检查密码字符类型

密码的强度通常取决于包含的字符类型。我们可以检查以下几种字符类型:

  • 大写字母(A-Z)
  • 小写字母(a-z)
  • 数字(0-9)
  • 特殊字符(如 !@#$%^&*() 等)
1.2 计算密码强度等级

根据字符类型的组合来评估密码的强度:

  • :密码只包含一种类型的字符(例如,只有小写字母)。
  • :密码包含两种类型的字符(例如,小写字母和数字)。
  • :密码包含三种或四种类型的字符(例如,大写字母、小写字母、数字和特殊字符)。
1.3 实现细节
  • 遍历密码中的每一个字符,并检查其类型。
  • 使用布尔变量记录每种字符类型是否存在。
  • 根据这些布尔变量来确定密码的强度等级。

2. 代码实现

以下是一个详细的实现代码示例,演示如何检测密码的安全性:

#include <iostream>
#include <string>
#include <cctype>

using namespace std;

// 检查密码的强度
string checkPasswordStrength(const string& password) {
    bool hasUpper = false;   // 是否包含大写字母
    bool hasLower = false;   // 是否包含小写字母
    bool hasDigit = false;   // 是否包含数字
    bool hasSpecial = false; // 是否包含特殊字符

    // 遍历密码中的每一个字符
    for (char ch : password) {
        if (isupper(ch)) {
            hasUpper = true;    // 发现大写字母
        } else if (islower(ch)) {
            hasLower = true;    // 发现小写字母
        } else if (isdigit(ch)) {
            hasDigit = true;    // 发现数字
        } else {
            hasSpecial = true;  // 发现特殊字符
        }
    }

    // 计算字符类型的总数
    int score = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0) + (hasDigit ? 1 : 0) + (hasSpecial ? 1 : 0);

    // 根据字符类型数返回强度等级
    if (score < 2) return "弱";
    if (score == 2) return "中";
    return "强";
}

int main() {
    string password;
    cout << "请输入密码: ";
    cin >> password;

    string strength = checkPasswordStrength(password);
    cout << "密码强度: " << strength << endl;

    return 0;
}

3. 代码原理

  1. 布尔变量

    • hasUpper, hasLower, hasDigit, hasSpecial 用于记录密码中是否包含大写字母、小写字母、数字和特殊字符。
  2. 字符检查

    • 使用 isupper(ch), islower(ch), isdigit(ch) 来检查字符是否属于某种类型。
    • 如果字符不属于上述任何一种类型,则认为是特殊字符。
  3. 强度等级

    • 根据布尔变量的状态来计算总的字符类型数。
    • 如果字符类型数少于 2,密码强度为“弱”。
    • 如果字符类型数等于 2,密码强度为“中”。
    • 如果字符类型数大于或等于 3,密码强度为“强”。

2.密码破解时间预估

目标

估算破解密码所需的时间,以评估密码的安全性。通常,这是通过计算密码的可能组合数来完成的。

方法
  1. 计算密码的可能性

    • 字符集:确定密码中可能的字符集。常见字符集包括:
      • 62 个字符:大写字母 (26) + 小写字母 (26) + 数字 (10)
      • 95 个字符:大写字母 + 小写字母 + 数字 + 特殊字符(如 !@#$%^&*()
    • 可能组合数:计算所有可能的密码组合数,这取决于密码长度和字符集大小。
  2. 计算破解时间

    • 假设每秒可以尝试 N 个密码(例如 4,000,000,000 个密码/秒),可以通过以下公式计算估算的破解时间:

预估破解时间的计算

  1. 计算密码的可能组合数

    计算所有可能的密码组合数是预估破解时间的关键。假设密码的长度为 L,并且密码字符集的大小为 C(例如,大写字母、小写字母、数字和特殊字符),那么密码的可能组合数可以通过以下公式计算:

插图的原因是CSDN的markdown编辑器读取不了这几个公式 但我的MARKDOWN编辑器可以读取

[\text{可能组合数} = C^L]

其中,( C ) 是字符集的大小,( L ) 是密码的长度。

  1. 计算破解时间

    假设每秒能够尝试 N 个密码(例如,4,000,000,000 次尝试),可以通过以下公式计算估算的破解时间:

    [\text{破解时间(秒)} = \frac{\text{可能组合数}}{N}]

    其中,( N ) 是每秒尝试的密码数量。

示例

假设密码长度为 8 个字符,字符集包含 62 个字符(大写字母、小写字母和数字),每秒可以尝试 4,000,000,000 个密码。
3. 示例
假设密码长度为 8,字符集大小为 62(包含大写字母、小写字母和数字),每秒尝试次数为 4,000,000,000,则:

在这里插入图片描述

  1. 转换单位
    将破解时间从秒转换为其他更易理解的单位,如分钟、小时、天、年等,可以使用以下公式:
    在这里插入图片描述
代码实现
#include <cmath>

double calculateCrackTime(const string& password) {
    double possibilities = 1;
    
    // 假设字符集中包含 62 个字符(大写字母 + 小写字母 + 数字)
    // 或 95 个字符(包括特殊字符)
    const double base = 62;  // 可以根据实际字符集调整
    
    for (char ch : password) {
        if (isdigit(ch) || isalpha(ch)) possibilities *= base;
        else possibilities *= 95;  // 特殊字符包含在 95 个字符集中
    }
    
    // 每秒 4,000,000,000 次尝试
    const double attemptsPerSecond = 4000000000.0;
    double timeInSeconds = possibilities / attemptsPerSecond;
    
    return timeInSeconds;
}

密码安全性检测主要是为了评估密码的强度,确保其不容易被破解。具体来说,我们可以通过检查密码的字符组成来评估其强度。以下是详细的步骤和代码示例,以及背后的原理。

总结

  • 密码安全性检测:通过检查密码的字符类型和组合来评估密码的强度。
  • 预估破解时间:通过计算密码的可能组合数和每秒破解速度来估算破解密码所需的时间。

效果图

在这里插入图片描述

源代码

注意

如果无法编译请在连接时加入以下参数

-std=c++11

代码

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iomanip>
#include <cctype>
#include <algorithm>
#include <map>

using namespace std;

// 数据结构
struct Account {
    int id;
    string platform;
    string username;
    string password;
};

// 密码管理器
class PasswordManager {
private:
    string masterPassword;
    vector<Account> accounts;
    const string dataFileName = "data.txt";
    const string passwordFileName = "password.dat";
    const int maxAttempts = 3;

    // 密码安全性检查
    string checkPasswordStrength(const string& password) {
        bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;
        for (char ch : password) {
            if (isupper(ch)) hasUpper = true;
            else if (islower(ch)) hasLower = true;
            else if (isdigit(ch)) hasDigit = true;
            else hasSpecial = true;
        }

        int score = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0) + (hasDigit ? 1 : 0) + (hasSpecial ? 1 : 0);
        if (score < 2) return "弱";
        if (score == 2) return "中";
        return "强";
    }

    // 计算密码破解时间
    double calculateCrackTime(const string& password) {
        // 假设每秒破解4000000000个密码
        double possibilities = 1;
        for (char ch : password) {
            if (isdigit(ch) || isalpha(ch)) possibilities *= 62;  // 数字 + 大小写字母
            else possibilities *= 95;  // 包含特殊符号
        }
        return possibilities / 4000000000.0;
    }

    // 保存管理器密码到文件
    void saveMasterPassword() {
        ofstream file(passwordFileName);
        if (file.is_open()) {
            file << masterPassword << endl;
            file.close();
        }
    }

    // 从文件加载管理器密码
    void loadMasterPassword() {
        ifstream file(passwordFileName);
        if (file.is_open()) {
            getline(file, masterPassword);
            file.close();
        }
    }

    // 检查密码是否匹配
    bool verifyPassword(const string& password) {
        return password == masterPassword;
    }

    // 保存数据到文件
    void saveData() {
        ofstream file(dataFileName);
        if (file.is_open()) {
            for (const auto& acc : accounts) {
                file << acc.id << " " << acc.platform << " " << acc.username << " " << acc.password << endl;
            }
            file.close();
        }
    }

    // 显示所有弱密码
    void displayWeakPasswords() {
        for (const auto& acc : accounts) {
            if (checkPasswordStrength(acc.password) == "弱") {
                cout << "ID: " << acc.id << ", 平台: " << acc.platform
                     << ", 账号: " << acc.username << ", 密码: " << acc.password << " (弱)" << endl;
            }
        }
    }

    // 显示重复的密码
    void displayDuplicatePasswords() {
        map<string, vector<Account>> platformAccounts;
        for (const auto& acc : accounts) {
            platformAccounts[acc.platform].push_back(acc);
        }

        for (const auto& pair : platformAccounts) {
            const auto& accList = pair.second;
            if (accList.size() > 1) {
                cout << "平台: " << pair.first << endl;
                for (const auto& acc : accList) {
                    cout << "ID: " << acc.id << ", 账号: " << acc.username << ", 密码: " << acc.password << endl;
                }
                cout << "-----------------------------" << endl;
            }
        }
    }

public:
    PasswordManager() {
        // 检查是否需要创建管理器密码
        loadMasterPassword();
        if (masterPassword.empty()) {
            cout << "首次启动,请设置管理器密码: ";
            cin >> masterPassword;
            saveMasterPassword();
        }
        else {
            // 校验管理器密码
            int attempts = 0;
            string password;
            while (attempts < maxAttempts) {
                cout << "输入管理器密码: ";
                cin >> password;
                if (verifyPassword(password)) {
                    break;
                } else {
                    cout << "密码错误!" << endl;
                    attempts++;
                }
            }
            if (attempts == maxAttempts) {
                cout << "尝试次数过多,程序退出。" << endl;
                exit(1);
            }
        }

        // 从文件加载数据
        ifstream file(dataFileName);
        if (file.is_open()) {
            string line;
            while (getline(file, line)) {
                Account acc;
                istringstream iss(line);
                iss >> acc.id >> acc.platform >> acc.username >> acc.password;
                accounts.push_back(acc);
            }
            file.close();
        }
    }

    // 添加第三方账号密码数据
    void addAccount() {
        Account acc;
        cout << "输入ID: ";
        cin >> acc.id;

        // 检查ID是否重复
        for (const auto& a : accounts) {
            if (a.id == acc.id) {
                cout << "ID " << acc.id << " 已经存在,请使用其他ID。" << endl;
                return;
            }
        }

        cout << "输入平台: ";
        cin >> acc.platform;
        cout << "输入账号: ";
        cin >> acc.username;
        cout << "输入密码: ";
        cin >> acc.password;

        string strength = checkPasswordStrength(acc.password);
        double crackTime = calculateCrackTime(acc.password);

        cout << "密码强度: " << strength << endl;
        cout << "估计破解时间: " << fixed << setprecision(2) << crackTime << " 秒" << endl;

        accounts.push_back(acc);
        saveData();
    }

    // 删除第三方账号密码数据
    void deleteAccount() {
        int id;
        cout << "输入要删除的账号ID: ";
        cin >> id;

        auto it = remove_if(accounts.begin(), accounts.end(), [id](const Account& acc) {
            return acc.id == id;
        });
        accounts.erase(it, accounts.end());
        saveData();
    }

    // 查找第三方账号密码数据
    void findAccount() {
        string platform;
        cout << "输入平台名称: ";
        cin >> platform;

        for (const auto& acc : accounts) {
            if (acc.platform.find(platform) != string::npos) {
                cout << "ID: " << acc.id << ", 平台: " << acc.platform
                     << ", 账号: " << acc.username << ", 密码: " << acc.password << endl;
            }
        }
    }

    // 修改第三方账号密码数据
    void modifyAccount() {
        int id;
        cout << "输入要修改的账号ID: ";
        cin >> id;

        for (auto& acc : accounts) {
            if (acc.id == id) {
                cout << "输入新的平台: ";
                cin >> acc.platform;
                cout << "输入新的账号: ";
                cin >> acc.username;
                cout << "输入新的密码: ";
                cin >> acc.password;
                saveData();
                return;
            }
        }
        cout << "未找到ID为" << id << "的账号。" << endl;
    }

    // 修改管理器密码
    void changeMasterPassword() {
        string oldPassword, newPassword;
        cout << "输入当前密码: ";
        cin >> oldPassword;

        if (oldPassword != masterPassword) {
            cout << "密码错误。" << endl;
            return;
        }

        cout << "输入新密码: ";
        cin >> newPassword;
        masterPassword = newPassword;
        saveMasterPassword();
    }

    // 显示所有弱密码
    void showWeakPasswords() {
        displayWeakPasswords();
    }

    // 显示重复的密码
    void showDuplicatePasswords() {
        displayDuplicatePasswords();
    }
};

int main() {
    PasswordManager pm;
    int choice;

    while (true) {
        cout << "1. 添加第三方账号密码\n";
        cout << "2. 删除第三方账号密码\n";
        cout << "3. 查找第三方账号密码\n";
        cout << "4. 修改第三方账号密码\n";
        cout << "5. 修改管理器密码\n";
        cout << "6. 显示所有弱密码\n";
        cout << "7. 显示重复密码\n";
        cout << "8. 退出\n";
        cout << "请选择: ";
        cin >> choice;

        switch (choice) {
            case 1: pm.addAccount(); break;
            case 2: pm.deleteAccount(); break;
            case 3: pm.findAccount(); break;
            case 4: pm.modifyAccount(); break;
            case 5: pm.changeMasterPassword(); break;
            case 6: pm.showWeakPasswords(); break;
            case 7: pm.showDuplicatePasswords(); break;
            case 8: return 0;
            default: cout << "无效选项。" << endl; break;
        }
    }
}

送一首

逻辑严密思无瑕,论证精辟显才华。
条理分明层次清,剖析深入浅出嘉。
例证丰富启思遐,见解独到惠众夸。
文章传世惠千家,启迪智慧泽八涯。

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

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

相关文章

C++ STL初阶(9):list 中关于reverse_iterator的实现

在完成vector和list的iterator相关部分的实践后来完成反向迭代器的实现 1. list的反向迭代器 书接上回&#xff0c;反向迭代器应当重新封装一个类。 反向迭代器和正向迭代器最大的区别就是&#xff0c;反向迭代器是倒着走的&#xff0c;所以最核心的逻辑就是将封装成-- 注意&am…

数字化转型-成就智慧智慧企业

数字化转型是企业迈向智慧化发展的关键路径&#xff0c;通过将先进的数字技术融入企业核心业务&#xff0c;构建智能化、数据驱动的运营模式&#xff0c;实现业务的全面升级与优化。智慧企业的实现依托于几个核心要素&#xff1a;首先是数字基础设施的建设&#xff0c;包括云计…

浅述TSINGSEE青犀EasyCVR视频汇聚平台与海康安防平台的区别对比

在我们的很多项目中都遇到过用户的咨询&#xff1a;TSINGSEE青犀EasyCVR视频汇聚平台与海康平台的区别在哪里&#xff1f;确实&#xff0c;在安防视频监控领域&#xff0c;EasyCVR视频汇聚平台与海康威视平台是两个备受关注的选择。它们各自具有独特的功能和优势&#xff0c;适…

RSS 源:在信息洪流中找回你的时间掌控权

简单介绍了 RSS 后&#xff0c;那么关键的一步就是建立好自己的 RSS 源了。 并不是所有平台都会提供 RSS 源&#xff0c;因此我们也没办法直接去订阅。 目前使用 RSS 的难题之一就是 RSS 源的匮乏&#xff0c;是无数人重新拥抱 RSS 的第一大障碍。 那么&#xff0c;如何去找…

全球化浪潮下的数据库革新:嘉里物流 TiDB 实践价值的设想

导读 本文来自 TiDB 社区武汉站——嘉里物流架构团队负责人肖飞老师的演讲《嘉里物流 & TiDB 在全球化业务场景中应用设想》。本次分享探讨了嘉里物流在全球化扩展中&#xff0c;将如何通过 TiDB 的强大功能应对海量数据挑战&#xff0c;优化技术架构&#xff0c;并提升决…

Adaptive Subgraph Neural Networkwith Reinforced Critical Structure Mining

1 Introduction graph mining area: 图挖掘领域 图具有广泛的局部结构&#xff1a;从节点、模体&#xff08;motifs&#xff09;到子图&#xff08;subgraph&#xff09; 主流研究表明&#xff1a;图的重要特征和突出模式是通过主要由一些关键局部结构&#xff08;如模体和子图…

html+css 实现hover 翻转按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目…

NCL的安装和运行;气象数据可视化;散点图、直方图、等值线图、箭头图、任意折线和任意图形、非规则网格、图形叠加、组图的绘制

NCAR Command Language&#xff08;NCL&#xff09;是由美国大气研究中心&#xff08;NCAR&#xff09;推出的一款用于科学数据计算和可视化的免费软件。它有着非常强大的文件输入和输出功能&#xff0c;可读写netCDF-3、netCDF-4 classic、HDF4、binary、ASCII数据&#xff0c…

LVS实验的三模式总结

文章目录 LVS的概念叙述NAT工作模式实战案例**思想&#xff1a;**NAT工作模式的优点NAT工作模式的缺点 NAT工作模式的应用场景大致配置 route&#xff1a;打开路由内核功能 部署DR模式集群案例工作思想&#xff1a;大致工作图如下思路模型 具体配置与事实步骤补充 防火墙标签解…

RCE漏洞复现

PHP命令执行常用函数 回调函数必须是命令执行和代码执行的函数&#xff0c;有两个条件 必须是函数&#xff0c;而且需要有函数运行的参数 危害&#xff1a;可以直接删除文件&#xff0c;添加文件&#xff0c;甚至可以添加用户 system --执行外部程序&#xff0c;并且显示输…

Ubuntu操作系统的基础操作和设置(详细且全面)(1)

前言 当Ubuntu系统被搭建完成以后&#xff0c;为了方便大家更容易上手&#xff0c;所以对常见的基础操作和设置进行讲解 1.支持中文显示&#xff0c;中文输入设置 1.1&#xff1a;支持中文显示 Ubuntu操作系统默认显示和输入的语言是英文。所以&#xff0c;如果你的英…

《虚拟之旅:开启无限可能的机器世界》简介:

1.Ubonto的介绍&#xff1a; Ubuntu 是一个流行的开源操作系统&#xff0c;基于 Linux 内核。 它具有以下一些特点和优势&#xff1a; 开源免费&#xff1a;任何人都可以免费使用、修改和分发。丰富的软件库&#xff1a;通过软件包管理器可以方便地安装各种应用程序。良好的…

Linux系统移植——开发板烧写(二)

目录&#xff1a; 目录&#xff1a; 一、什么是EMMC分区&#xff1f; 1.1 eMMC分区 1.2 分区的管理 二、相关命令介绍&#xff1a; 2.1 mmc 2.1.1 主要功能 2.1.2 示例用法 2.2 fdisk 2.2.1 基本功能 2.2.2 交互模式常用命令 2.2.3 注意事项 三、U-BOOT烧写 3.1 mmc命令 3.2 f…

Java并发面试题汇总

文章目录 线程什么是线程和进程?请简要描述线程与进程的关系,区别及优缺点?程序计数器、虚拟机栈、虚拟机栈、堆和方法区如何创建线程?线程的生命周期什么是线程上下文切换?Thread#sleep() 方法和 Object#wait() 方法对比为什么 wait() 方法不定义在 Thread 中?为什么 sle…

【解压即玩】PC端最好用最漂亮的前端CoinOPS整合包186G 复古带遮罩和滤镜,怀旧拉满

这是大神做的一个整合包&#xff0c;让游戏界面更加的漂亮&#xff0c;如图&#xff0c;下面是游戏选择画面&#xff0c;右侧是滚动的圆盘&#xff0c;左侧显示游戏的画面&#xff1a; 实际游戏时的界面是这样的&#xff1a; 应当是目前最漂亮的游戏界面了。之前有人说在电脑上…

sp eric靶机

扫描IP 端口扫描 nmap 192.168.111.146 -p- -sV 目录扫描 # 使用命令 dirsearch -u "http://192.168.111.146" 访问靶机IP地址 拼接访问 admin.php &#xff0c;发现登录框界面&#xff0c;尝试sql注入&#xff0c;弱口令等&#xff0c;没有结果 看看 .git &#…

【C语言篇】C语言常考及易错题整理DAY2

文章目录 C语言常考及易错题整理选择题编程题至少是其他数字两倍的最大数两个数组的交集图片整理寻找数组的中心下标多数元素除自身以外数组的乘积不使用加减乘除求两个数的加法 C语言常考及易错题整理 选择题 下列 for 循环的次数为&#xff08; &#xff09; for(int i 0…

高可用keepalived详解---干货满满(企业应用示例)

目录 一、master/master 的 Keepalived 双主架构 1.1 ka1部署 1.2 ka2部署 1.3 重启测试 二、实现ipvs高可用 (keepalivedlvs) 2.1 ipvs的相关配置 2.1.1 虚拟服务器配置架构 2.1.2 virtual server &#xff08;虚拟服务器&#xff09;的定义格式 2.1.3 虚拟服务器…

四十、大数据技术之Kafka3.x(3)

&#x1f33b;&#x1f33b; 目录 一、Kafka Broker1.1 Kafka Broker工作流程1.1.1 Zookeeper 存储的Kafka信息1.1.2 Kafka Broker 总体工作流程1.1.3 Broker 重要参数 1.2 生产经验——节点服役和退役1.2.1 服役新节点1.2.2 退役旧节点 1.3 Kafka 副本1.3.1 副本基本信息1.3.2…

线程知识及编程

线程定义 在Python中&#xff0c;想要实现多任务还可以使用多线程来完成。 为什么使用多线程&#xff1f; 进程是分配资源的最小单位 , 一旦创建一个进程就会分配一定的资源 , 就像跟两个人聊QQ就需要打开两个QQ软件一样是比较浪费资源的 . 线程是程序执行的最小单位 , 实际…