C++实现rabbitmq生产者消费者

news2025/3/22 7:15:31

RabbitMQ是一个开源的消息队列系统,它实现了高级消息队列协议(AMQP),

特点

  • 可靠性:通过持久化、镜像队列等机制保证消息不丢失,确保消息可靠传递。
  • 灵活的路由:提供多种路由方式,如直连、主题、扇形等,可根据不同的业务需求进行灵活配置。
  • 多语言支持:支持多种编程语言,如Java、Python、C++、Ruby等,方便不同技术栈的开发者使用。
  • 高可用性:可以通过集群方式实现高可用性,避免单点故障,保证系统的稳定运行。
  • 易于管理:提供了可视化的管理界面,方便管理员对队列、交换机、消息等进行监控和管理。

核心概念

  • 消息:应用程序之间传递的数据单元。
  • 队列:用于存储消息的缓冲区,消息会在队列中等待消费者来获取。
  • 交换机:接收生产者发送的消息,并根据路由键将消息路由到相应的队列。
  • 绑定:将交换机和队列通过路由键进行关联,建立路由规则。
  • 生产者:负责发送消息到RabbitMQ服务器的应用程序。
  • 消费者:从RabbitMQ服务器获取消息并进行处理的应用程序。

工作原理

  1. 生产者将消息发送到交换机,消息中包含路由键等信息。
  2. 交换机根据路由键和绑定规则,将消息路由到对应的队列。
  3. 消费者从队列中获取消息并进行处理。

应用场景

  • 异步处理:将一些耗时的操作如发送邮件、生成报表等放在消息队列中,由消费者异步处理,提高系统的响应速度。
  • 系统解耦:不同模块之间通过消息队列进行通信,降低模块之间的耦合度,使得各个模块可以独立扩展和维护。
  • 流量削峰:在高并发场景下,将大量的请求放入消息队列中,由消费者按照一定的速度进行处理,避免系统因瞬间高流量而崩溃。

C++实现rabbitmq生产者消费者


// MFCRABBITMQDlg.h: 头文件
//

#pragma once
#include <iostream>
#include <string>
#include <amqp.h>
#include <amqp_tcp_socket.h>
#pragma comment(lib , "rabbitmq.lib")

// CMFCRABBITMQDlg 对话框
class CMFCRABBITMQDlg : public CDialogEx
{
// 构造
public:
	CMFCRABBITMQDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_MFCRABBITMQ_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButtonProduct();
	void CMFCRABBITMQDlg::sendMessageToRabbitMQ(const std::string& message);
	void CMFCRABBITMQDlg::receiveMessagesFromRabbitMQ();
	afx_msg void OnBnClickedButtonConsumer();
	void CMFCRABBITMQDlg::showLog(CString p_str_log);
	CString m_CstrLog;
	CEdit m_ctrlLog;
};


// MFCRABBITMQDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "MFCRABBITMQ.h"
#include "MFCRABBITMQDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFCRABBITMQDlg 对话框



CMFCRABBITMQDlg::CMFCRABBITMQDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MFCRABBITMQ_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCRABBITMQDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_LOG, m_ctrlLog);
}

BEGIN_MESSAGE_MAP(CMFCRABBITMQDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_PRODUCT, &CMFCRABBITMQDlg::OnBnClickedButtonProduct)
    ON_BN_CLICKED(IDC_BUTTON_CONSUMER, &CMFCRABBITMQDlg::OnBnClickedButtonConsumer)
END_MESSAGE_MAP()


// CMFCRABBITMQDlg 消息处理程序

BOOL CMFCRABBITMQDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMFCRABBITMQDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMFCRABBITMQDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCRABBITMQDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CMFCRABBITMQDlg::sendMessageToRabbitMQ(const std::string& message)
{
    amqp_connection_state_t conn;
    amqp_socket_t* socket = NULL;
    int status;

    // 初始化连接
    conn = amqp_new_connection();
    socket = amqp_tcp_socket_new(conn);
    if (!socket) {
        std::cerr << "Failed to create TCP socket" << std::endl;
        return;
    }

    // 连接到 RabbitMQ 服务器
    status = amqp_socket_open(socket, "localhost", 5672);
    if (status) {
        std::cerr << "Failed to open TCP socket" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 登录到 RabbitMQ 服务器
    amqp_rpc_reply_t loginReply = amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
    if (loginReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to login to RabbitMQ" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 打开通道
    amqp_channel_open(conn, 1);
    amqp_rpc_reply_t openReply = amqp_get_rpc_reply(conn);
    if (openReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to open channel" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 声明队列
    amqp_queue_declare(conn, 1, amqp_cstring_bytes("my_queue"), 0, 0, 0, 0, amqp_empty_table);
    amqp_rpc_reply_t queueDeclareReply = amqp_get_rpc_reply(conn);
    if (queueDeclareReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to declare queue" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 发布消息到队列
    amqp_basic_properties_t props;
    props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
    props.content_type = amqp_cstring_bytes("text/plain");
    props.delivery_mode = 2; // 持久化消息

    amqp_basic_publish(conn,
        1,
        amqp_cstring_bytes(""),  // 默认交换器
        amqp_cstring_bytes("my_queue"),
        0,
        0,
        &props,
        amqp_cstring_bytes(message.c_str()));

    // 检查发布结果
    amqp_rpc_reply_t publishReply = amqp_get_rpc_reply(conn);
    if (publishReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to publish message" << std::endl;
    }
    else {
        std::cout << "Message sent: " << message << std::endl;
    }

    // 关闭通道和连接
    amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
    amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
    amqp_destroy_connection(conn);
}


void CMFCRABBITMQDlg:: receiveMessagesFromRabbitMQ()
{
    amqp_connection_state_t conn;
    amqp_socket_t* socket = NULL;
    int status;

    // 初始化连接
    conn = amqp_new_connection();
    socket = amqp_tcp_socket_new(conn);
    if (!socket) {
        std::cerr << "Failed to create TCP socket" << std::endl;
        return;
    }

    // 连接到 RabbitMQ 服务器
    status = amqp_socket_open(socket, "localhost", 5672);
    if (status) {
        std::cerr << "Failed to open TCP socket" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 登录到 RabbitMQ 服务器
    amqp_rpc_reply_t loginReply = amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
    if (loginReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to login to RabbitMQ" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 打开通道
    amqp_channel_open(conn, 1);
    amqp_rpc_reply_t openReply = amqp_get_rpc_reply(conn);
    if (openReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to open channel" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 声明队列
    amqp_queue_declare(conn, 1, amqp_cstring_bytes("my_queue"), 0, 0, 0, 0, amqp_empty_table);
    amqp_rpc_reply_t queueDeclareReply = amqp_get_rpc_reply(conn);
    if (queueDeclareReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to declare queue" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    // 开始消费消息
    amqp_basic_consume(conn, 1, amqp_cstring_bytes("my_queue"), amqp_empty_bytes, 0, 1, 0, amqp_empty_table);
    amqp_rpc_reply_t consumeReply = amqp_get_rpc_reply(conn);
    if (consumeReply.reply_type != AMQP_RESPONSE_NORMAL) {
        std::cerr << "Failed to start consuming messages" << std::endl;
        amqp_destroy_connection(conn);
        return;
    }

    std::cout << "Waiting for messages. To exit press CTRL+C" << std::endl;
    showLog(_T("消费者开始监听:"));
    while (true) {
        amqp_rpc_reply_t reply;
        amqp_envelope_t envelope;

        amqp_maybe_release_buffers(conn);
        reply = amqp_consume_message(conn, &envelope, NULL, 0);

        if (AMQP_RESPONSE_NORMAL != reply.reply_type) {
            break;
        }
        static int t_count = 0;
        t_count++;
        std::cout << "Received message: ";
        char* p1 = static_cast<char*>(envelope.message.body.bytes);
        char* p = new char[envelope.message.body.len+1]();
        // strcpy_s(p , envelope.message.body.len, "11");
        for (size_t i = 0; i < envelope.message.body.len; ++i)
        {
            p[i] = p1[i];
        }
        std::cout << std::endl;
        CString t_Cstr = (CString)p;
        CString t_CstrCount;
        t_CstrCount.Format(_T("%d  ->"), t_count);
        

        CString t_tep = t_CstrCount + t_Cstr;
        showLog(t_tep);
        delete[]p;
        amqp_destroy_envelope(&envelope);
    }

    // 关闭通道和连接
    amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
    amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
    amqp_destroy_connection(conn);
}

// ch:取流线程 | en:Grabbing thread
unsigned int __stdcall SendThread(void* pUser)
{
    if (pUser)
    {
        CMFCRABBITMQDlg* Gthis = (CMFCRABBITMQDlg*)pUser;
        CString t_CstrSend;
       
        for (int i = 0; i < 1000000; ++i)
        {
            Gthis->GetDlgItemText(IDC_EDIT_TEXT, t_CstrSend);
            std::string t_strSend = (CT2A)t_CstrSend;
            Gthis->sendMessageToRabbitMQ(t_strSend);
            Sleep(1);
        }
        

        return 0;
    }

    return -1;
}

void CMFCRABBITMQDlg::OnBnClickedButtonProduct()
{
        unsigned int nThreadID = 0;
        void* m_hGrabThread = (void*)_beginthreadex(NULL, 0, SendThread, this, 0, &nThreadID);
        if (NULL == m_hGrabThread)
        {
            showLog(_T("消费者创建线程失败"));
            return;
        }

}

// ch:取流线程 | en:Grabbing thread
unsigned int __stdcall ConsumThread(void* pUser)
{
    if (pUser)
    {
        CMFCRABBITMQDlg* Gthis = (CMFCRABBITMQDlg*)pUser;
       
        Gthis->receiveMessagesFromRabbitMQ();

        return 0;
    }

    return -1;
}

void CMFCRABBITMQDlg::OnBnClickedButtonConsumer()
{
    unsigned int nThreadID = 0;
    void* m_hGrabThread = (void*)_beginthreadex(NULL, 0, ConsumThread, this, 0, &nThreadID);
    if (NULL == m_hGrabThread)
    {
        showLog(_T("消费者创建线程失败"));
        return;
    }
}

void CMFCRABBITMQDlg::showLog(CString p_str_log)
{
    int t_intLine = m_ctrlLog.GetLineCount();
    if (t_intLine == 1000)
    {
        m_CstrLog = _T("");
    }
    SYSTEMTIME timeCur;
    GetLocalTime(&timeCur);
    char t_logbuffer[1024] = { 0 };
    sprintf_s(t_logbuffer, ("[%04d%02d%02d_%02d:%02d:%02d:%03d] ")
        , timeCur.wYear, timeCur.wMonth, timeCur.wDay
        , timeCur.wHour, timeCur.wMinute, timeCur.wSecond, timeCur.wMilliseconds);

    p_str_log += "\r\n";
    m_CstrLog += t_logbuffer;
    m_CstrLog += p_str_log;
    m_ctrlLog.SetWindowTextW(m_CstrLog);
    m_ctrlLog.LineScroll(m_ctrlLog.GetLineCount() - 1, 0);
 
}

在这里插入图片描述

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

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

相关文章

在VMware上部署【Ubuntu】

镜像下载 国内各镜像站点均可下载Ubuntu镜像&#xff0c;下面例举清华网站 清华镜像站点&#xff1a;清华大学开源软件镜像站 | Tsinghua Open Source Mirror 具体下载步骤如下&#xff1a; 创建虚拟机 准备&#xff1a;在其他空间大的盘中创建存储虚拟机的目录&#xff0c…

又双叒叕Scrapy爬虫相关的面试题及详细解答

Scrapy是Python开发的一个快速、高层次的网络爬虫框架,专注于高效抓取网页并提取结构化数据。其核心设计基于异步处理机制,适合大规模数据采集任务。 文章目录 基础概念1. Scrapy框架的核心组件有哪些?架构与流程2. 描述Scrapy的工作流程核心组件详解3. 如何自定义Item Pipe…

使用STM32CubeMX+DMA+空闲中断实现串口接收和发送数据(STM32G070CBT6)

1.STM32CubeMX配置 &#xff08;1&#xff09;配置SYS &#xff08;2&#xff09;配置RCC &#xff08;3&#xff09;配置串口&#xff0c;此处我用的是串口4&#xff0c;其他串口也是一样的 &#xff08;4&#xff09;配置DMA&#xff0c;将串口4的TX和RX添加到DMA中 &#…

【视觉提示学习】3.21论文随想

. . Frontiers of Information Technology & Electronic Engineering. 2024, 25(1): 42-63 https://doi.org/10.1631/FITEE.2300389 中文综述&#xff0c;根据里面的架构&#xff0c;把视觉提示学习分成两类&#xff0c;一类是单模态提示学习&#xff08;以vit为代表&…

(一)丶Windows安装RabbitMQ可能会遇到的问题

一丶可能会忘了配置ERLang的环境变量 二丶执行命令时报错 第一步 rabbitmq-plugins enable rabbitmq_management 第二部 rabbitmqctl status 三丶修改.erlang.cookie 文件 1.找到C盘目下的.erlang.cookie文件 C:\Users\admin\.erlang.cookie C:\Windows\System32\config\sys…

Mistral AI发布开源多模态模型Mistral Small 3.1:240亿参数实现超越GPT-4o Mini的性能

法国人工智能初创公司Mistral AI于2025年3月正式推出新一代开源模型Mistral Small 3.1 &#xff0c;该模型凭借240亿参数的轻量级设计&#xff0c;在多项基准测试中表现优异&#xff0c;甚至超越了Google的Gemma 3和OpenAI的GPT-4o Mini等主流专有模型。 1、核心特性与优势 多…

springboot整合mybatis-plus【详细版】

目录 一&#xff0c;简介 1. 什么是mybatis-plus2.mybatis-plus特点 二&#xff0c;搭建基本环境 1. 导入基本依赖&#xff1a;2. 编写配置文件3. 创建实体类4. 编写controller层5. 编写service接口6. 编写service层7. 编写mapper层 三&#xff0c;基本知识介绍 1. 基本注解 T…

Qt之MVC架构MVD

什么是MVC架构&#xff1a; MVC模式&#xff08;Model–view–controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controll…

深度解析学术论文成果评估(Artifact Evaluation):从历史到现状

深度解析学术论文成果评估(Artifact Evaluation)&#xff1a;从历史到现状 引言 在计算机科学和工程领域的学术研究中&#xff0c;可重复性和可验证性越来越受到重视。随着实验性研究的复杂性不断增加&#xff0c;确保研究成果可以被其他研究者验证和构建变得尤为重要。这一需…

二分查找上下界问题的思考

背景 最近在做力扣hot100中的二分查找题目时&#xff0c;发现很多题目都用到了二分查找的变种问题&#xff0c;即二分查找上下界问题&#xff0c;例如以下题目&#xff1a; 35. 搜索插入位置 74. 搜索二维矩阵 34. 在排序数组中查找元素的第一个和最后一个位置 它们不同于查找…

关于FastAPI框架的面试题及答案解析

FastAPl是一个现代、快速(高性能)的Web框架,用于构建API,基于Python3.7+的类型提示功能。它由Python开发者SebastianRamirez创建,并且使用了Starlette作为其核心组件以及Pydantic进行数据验证。 文章目录 基础篇1. FastAPI的核心优势是什么?2. 如何定义一个GET请求路由?…

HashMap添加元素的流程图

文章目录 JDK7 vs JDK8 的 HashMap 结构变化Java8 中哈希表的红黑树优化机制HashMap 添加元素的完整流程解析1. 计算 key 的哈希值并确定索引2. 检查该索引位置是否已有元素3. 处理哈希冲突4. 判断当前存储结构&#xff08;链表还是红黑树&#xff09;5. 判断链表长度是否超过 …

面向医药仓储场景下的药品分拣控制策略方法 研究(大纲)

面向医药仓储场景下的药品分拣控制策略方法研究 基于多机器人协同与智能调度的分拣系统设计 第一章 绪论 1.1 研究背景与意义 医药仓储自动化需求&#xff1a; 人工分拣效率低、出错率高&#xff08;如药品批次混淆、过期风险&#xff09;温控药品&#xff08;如疫苗、生物制…

AI大模型介绍

大模型介绍 大模型是指具有大规模参数和复杂计算结构的机器学习模型&#xff0c;通常由深度神经网络构建而成&#xff0c;拥有数十亿甚至数千亿个参数 开发大模型不是从0开始&#xff0c;是建立在已有的大模型基座模型上做开发&#xff0c;构建企业知识库&#xff08;向量数据库…

OpenPCDet详细部署与复现

OpenPCDet简介 OpenPCDet是一个用于3D目标检测的开源工具箱&#xff0c;它提供了多种数据集的加载器&#xff0c;支持多种模型&#xff0c;并且易于扩展。 本人使用硬件与环境 Linux操作系统&#xff08;Ubuntu20.04&#xff09; Python环境&#xff08;Anaconda下独立创建&…

同旺科技USB to I2C 适配器 ---- 指令之间延时功能

所需设备&#xff1a; 内附链接 1、同旺科技USB to I2C 适配器 1、指令之间需要延时发送怎么办&#xff1f;循环过程需要延时怎么办&#xff1f;如何定时发送&#xff1f;现在这些都可以轻松解决&#xff1b; 2、只要在 “发送数据” 栏的Delay单元格里面输入相应的延迟时间就…

网络华为HCIA+HCIP NFV

目录 NFV关键技术&#xff1a;虚拟化 NFV关键技术&#xff1a;云化 NFV架构 NFV标准架构 ​编辑 NFV架构功能模块 NFV架构接口 NFV关键技术&#xff1a;虚拟化 在NFV的道路上&#xff0c;虚拟化是基础&#xff0c;云化是关键。传统电信网络中&#xff0c;各个网元都是…

MySQL0基础学习记录-下载与安装

下载 下载地址&#xff1a; &#xff08;Windows&#xff09;https://dev.mysql.com/downloads/file/?id536787 安装 直接点next&#xff0c;出现&#xff1a; 点execute 然后一直next到这页&#xff1a; next 然后需要给root设置一个密码&#xff1a; 在next。。很多页…

集成学习(下):Stacking集成方法

一、Stacking的元学习革命 1.1 概念 Stacking&#xff08;堆叠法&#xff09; 是一种集成学习技术&#xff0c;通过组合多个基学习器&#xff08;base learner&#xff09;的预测结果&#xff0c;并利用一个元模型&#xff08;meta-model&#xff09;进行二次训练&#xff0c…

背包问题——动态规划的经典问题包括01背包问题和完全背包问题

01背包问题&#xff1a;给你多个物品每个物品只能选一次&#xff0c;要你在不超过背包容积&#xff08;或者恰好等于&#xff09;的情况下选择装价值最大的组合。如果没有动态规划的基础其实是很难理解这个问题的&#xff0c;所以看这篇文章之前先去学习一下动态规划的基本思想…