posix线程的优先级测试

news2024/11/23 21:02:54

如果创建的线程不够多,有些问题是体现不出来的。

优先级打印:

测试目的:输出三种调度模式下的最大优先级和最小优先级

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <errno.h>
#include <sys/wait.h>
#include <netinet/tcp.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)


int main(){
    int min;
    int max;
    min = sched_get_priority_min(SCHED_OTHER);
    max = sched_get_priority_max(SCHED_OTHER);
    DEBUG_INFO("SCHED_OTHER min = %d,max = %d",min,max);

    min = sched_get_priority_min(SCHED_RR);
    max = sched_get_priority_max(SCHED_RR);
    DEBUG_INFO("SCHED_RR min = %d,max = %d",min,max);

    min = sched_get_priority_min(SCHED_FIFO);
    max = sched_get_priority_max(SCHED_FIFO);
    DEBUG_INFO("SCHED_FIFO min = %d,max = %d",min,max);


    return 0;
}

执行结果:

main:25 -- SCHED_OTHER min = 0,max = 0
main:29 -- SCHED_OTHER min = 1,max = 99
main:33 -- SCHED_OTHER min = 1,max = 99

测试一:先创建10个线程。

使用默认属性。

#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

std::map<pthread_t ,int> thread_index_map;

struct mystruct{
    int index;
    pthread_t thread;

};

void clean_up_resource(void *arg){
    struct mystruct *pms = (struct mystruct *)arg;
    DEBUG_INFO("delete thread index = %d\n", pms->index);
    free(arg);
}

void *func(void *arg){
    struct mystruct *pms = (struct mystruct *)arg;
    static pthread_t thread_id = pthread_self();
    pthread_cleanup_push(clean_up_resource,arg);
    
    while(1){
        for(int i = 0;i < 10000000;i++){

        }
        break;
    }
    DEBUG_INFO("index = %d",pms->index);
    return 0;
    pthread_cleanup_pop(0);
}

int main(int argc, char**){
    for(int i=0; i < 10; i++){
        pthread_t t;
        struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
        pms->index = i;
        int ret = pthread_create(&t, NULL, func,pms);
        if(ret != 0){
            perror("pthread_create");
        }
    }
    while(1){
        sleep(1);
    }
}

 执行结果:

main:44 -- pid = 39495
func:37 -- index = 3
func:37 -- index = 8
func:37 -- index = 0
func:37 -- index = 4
func:37 -- index = 6
func:37 -- index = 9
func:37 -- index = 2
func:37 -- index = 7
func:37 -- index = 5
func:37 -- index = 1

pstree -p命令的执行截图

 上面我们看到输出的index的值,不是倒叙也不是正序,而是乱序的,现在,我们需要设置线程的优先级,让他们有序的运行,如何操作呢。

测试二:线程的清理

捕获信号SIGINT,在SIGINT信号处理函数中,结束10个线程。然后

#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#include <list>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

std::map<pthread_t ,int> thread_index_map;
typedef void (*sighandler)(int signo);
struct mystruct{
    int index;
    pthread_t thread;

};

void clean_up_resource(void *arg){
    struct mystruct *pms = (struct mystruct *)arg;
    DEBUG_INFO("delete thread index = %d\n", pms->index);
    free(arg);
}
std::list<pthread_t> pthread_list;
void *func(void *arg){
    pthread_list.push_back(pthread_self());
    struct mystruct *pms = (struct mystruct *)arg;
    static pthread_t thread_id = pthread_self();
    pthread_cleanup_push(clean_up_resource,arg);
    
    while(1){
        for(int i = 0;i < 10000000;i++){

        }
        break;
    }
    DEBUG_INFO("index = %d",pms->index);
    while(1)sleep(1);
    return 0;
    pthread_cleanup_pop(0);
}



void sig_func(int signo){
    auto it = pthread_list.begin();
    DEBUG_INFO("%lu",pthread_list.size());
    for(;it != pthread_list.end();it++){
        pthread_cancel(*it);
    }
    DEBUG_INFO("good bye");
    sleep(2);
    exit(0);
}

int main(int argc, char**){
    sighandler sig_ret;
    sig_ret = signal(SIGINT, sig_func);
    if(sig_ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    DEBUG_INFO("pid = %u",getpid());
    for(int i=0; i < 10; i++){
        pthread_t t;
        struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
        pms->index = i;
        int ret = pthread_create(&t, NULL, func,pms);
        if(ret != 0){
            perror("pthread_create");
        }
    }
    while(1){
        sleep(1);
    }
    return 0;
}

执行结果:

main:65 -- pid = 50827
func:39 -- index = 1
func:39 -- index = 4
func:39 -- index = 2
func:39 -- index = 3
func:39 -- index = 0
func:39 -- index = 5
func:39 -- index = 6
func:39 -- index = 8
func:39 -- index = 7
func:39 -- index = 9
^Csig_func:49 -- 10
sig_func:53 -- good bye
clean_up_resource:23 -- delete thread index = 0

clean_up_resource:23 -- delete thread index = 4

clean_up_resource:23 -- delete thread index = 1

clean_up_resource:23 -- delete thread index = 3

clean_up_resource:23 -- delete thread index = 5

clean_up_resource:23 -- delete thread index = 8

clean_up_resource:23 -- delete thread index = 9

clean_up_resource:23 -- delete thread index = 2

clean_up_resource:23 -- delete thread index = 7

clean_up_resource:23 -- delete thread index = 6

按下CTRL+C后,sig_func被执行,开始遍历删除链表中的线程。最后退出进程。为了让删除动作成功完成,执行exit(0)之前先休眠2秒。

 测试三:线程的属性

pthread_attr_init函数

NAME
       pthread_attr_init, pthread_attr_destroy - initialize and destroy thread attributes object

SYNOPSIS
       #include <pthread.h>

       int pthread_attr_init(pthread_attr_t *attr);
       int pthread_attr_destroy(pthread_attr_t *attr);

       Compile and link with -pthread.

pthread_getattr_np函数 

NAME
       pthread_getattr_np - get attributes of created thread

SYNOPSIS
       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <pthread.h>

       int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);

       Compile and link with -pthread.

 pthread_attr_t结构体

 pthread_attr_init函数

NAME
       pthread_attr_init, pthread_attr_destroy - initialize and destroy thread attributes object

SYNOPSIS
       #include <pthread.h>

       int pthread_attr_init(pthread_attr_t *attr);
       int pthread_attr_destroy(pthread_attr_t *attr);

       Compile and link with -pthread.

 线程的优先级是经常设置的属性,由两个函数进行控制:pthread_attr_getschedparam()函数获得线程的优先级设置;函数pthread_attr_setschedparam()设置线程的优先级。

pthread_attr_setschedparam函数 

NAME
       pthread_attr_setschedparam, pthread_attr_getschedparam - set/get scheduling parameter attributes in thread attributes object

SYNOPSIS
       #include <pthread.h>

       int pthread_attr_setschedparam(pthread_attr_t *attr,
                                      const struct sched_param *param);
       int pthread_attr_getschedparam(const pthread_attr_t *attr,
                                      struct sched_param *param);

       Compile and link with -pthread.

结构体struct sched_param

struct sched_param {
               int sched_priority;     /* Scheduling priority */
           };

pthread_testcancel函数 

NAME
       pthread_testcancel - request delivery of any pending cancellation request

SYNOPSIS
       #include <pthread.h>

       void pthread_testcancel(void);

       Compile and link with -pthread.

schedpolicy:这个属性控制线程的调度方式。它的取值可以是SCHED_OTHER、SCHED_RP和SCHED_FIFO。这个属性的默认值为SCHED_OTHER。另外两种调度方式只能用于以超级用户权限运行的进程,因为它们都具备实时调度的功能,但在行为上略有区别。SCHED_RP使用循环(round-robin)调度机制,而SCHED_FIFO使用“先进先出”策略。

测试三:优先级测试

#ifndef _GNU_SOURCE
#define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */
#endif
#define _REENTRANT
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#include <list>
#include <sched.h>
#include <atomic>
using namespace std;

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

std::map<pthread_t ,int> thread_index_map;
typedef void (*sighandler)(int signo);
struct mystruct{
    int index;
    pthread_t thread;
    pthread_attr_t attr;
    struct sched_param sched;


};

void clean_up_resource(void *arg){
    struct mystruct *pms = (struct mystruct *)arg;
    DEBUG_INFO("delete thread index = %d\n", pms->index);
    pthread_attr_destroy(&pms->attr);
    free(arg);
}
std::list<pthread_t> pthread_list;
// std::atomic_bool start = false;
atomic<long> start(0);
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *func(void *arg){
    pthread_list.push_back(pthread_self());
    struct mystruct *pms = (struct mystruct *)arg;
    static pthread_t thread_id = pthread_self();
    pthread_cleanup_push(clean_up_resource,arg);

    // pthread_mutex_lock(&mtx);
    // while(start == 0){
    //     pthread_cond_wait(&cond,&mtx);
    // }
    // pthread_mutex_unlock(&mtx);
    int ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &pms->sched);
    if (ret != 0) {
        perror("pthread_setschedparam");
        exit(-1);
    }
    while(start == 0){}
    DEBUG_INFO("start thread = %d",pms->index);
    
    while(1){
        for(int i = 0;i < 100;i++){
            pthread_testcancel();
            for(int j = 0;j < 100;j++){usleep(1);}
        }
        break;
    }
    DEBUG_INFO("index = %d",pms->index);
    while(1)sleep(1);
    return 0;
    pthread_cleanup_pop(0);
}

void sig_func(int signo){
    auto it = pthread_list.begin();
    DEBUG_INFO("%lu",pthread_list.size());
    for(;it != pthread_list.end();it++){
        
        pthread_cancel(*it);
    }
    DEBUG_INFO("good bye");
    sleep(2);
    exit(0);
}

int main(int argc, char**){
    sighandler sig_ret;
    sig_ret = signal(SIGINT, sig_func);
    if(sig_ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    DEBUG_INFO("pid = %u",getpid());
    for(int i=0; i < 10; i++){
        pthread_t t;
        struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
        if(!pms){
            perror("malloc");
            raise(SIGINT);
            while(1)sleep(1);
        }
        pms->index = i;       

        pthread_attr_init(&pms->attr);
        pthread_attr_getschedparam(&pms->attr,&pms->sched);
        DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
        pthread_attr_setschedpolicy(&pms->attr,SCHED_FIFO);//SCHED_OTHER);//SCHED_RP);//SCHED_FIFO);
        pms->sched.sched_priority = (i + 1)*5;
        pthread_attr_setschedparam(&pms->attr,&pms->sched);

        pthread_attr_getschedparam(&pms->attr,&pms->sched);
        DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);

        
        int ret = pthread_create(&t, NULL, func,pms);
        if(ret != 0){
            perror("malloc");
            raise(SIGINT);
            free(pms);            
            
        }
    }
    start = 1;
    //pthread_cond_signal(&cond);
    pthread_cond_broadcast(&cond);
    while(1){
        sleep(1);
    }
    return 0;
}

main:93 -- pid = 87681
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 5
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 10
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 15
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 20
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 25
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 30
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 35
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 40
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 45
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 50
func:59 -- start thread = 4
func:59 -- start thread = 0
func:59 -- start thread = 1
func:59 -- start thread = 3
func:59 -- start thread = 6
func:59 -- start thread = 5
func:59 -- start thread = 7
func:59 -- start thread = 9
func:59 -- start thread = 2
func:59 -- start thread = 8
func:68 -- index = 9
func:68 -- index = 6
func:68 -- index = 7
func:68 -- index = 8
func:68 -- index = 4
func:68 -- index = 2
func:68 -- index = 3
func:68 -- index = 5
func:68 -- index = 0
func:68 -- index = 1

 线程9优先级最高,所以先执行完成,线程0优先级最低,倒数第二完成。只能说整体上能看出来是优先级的趋势是对的了。因为是多核的关系吗。所以不是纯正的降序。

在单核的ARM板上运行,如下所示,没有达到我心中的降序的效果啊。4都最先完成了。但是每次执行完成的数序确实固定的,这...

func:68 -- index = 4
func:68 -- index = 5
func:68 -- index = 6
func:68 -- index = 7
func:68 -- index = 3
func:68 -- index = 2
func:68 -- index = 8
func:68 -- index = 9
func:68 -- index = 1
func:68 -- index = 0

 优化后的代码

#ifndef _GNU_SOURCE
#define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */
#endif
#ifndef _REENTRANT
#define _REENTRANT
#endif
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#include <list>
#include <sched.h>
#include <atomic>
using namespace std;

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

std::map<pthread_t ,int> thread_index_map;
typedef void (*sighandler)(int signo);
struct mystruct{
    int index;
    pthread_t thread;
    pthread_attr_t attr;
    struct sched_param sched;


};

void clean_up_resource(void *arg){
    struct mystruct *pms = (struct mystruct *)arg;
    DEBUG_INFO("delete thread index = %d\n", pms->index);
    pthread_attr_destroy(&pms->attr);
    free(arg);
}
std::list<pthread_t> pthread_list;
// std::atomic_bool start = false;
atomic<long> start(0);
atomic<long> counter(0);
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *func(void *arg){
    pthread_list.push_back(pthread_self());
    struct mystruct *pms = (struct mystruct *)arg;
    static pthread_t thread_id = pthread_self();
    pthread_cleanup_push(clean_up_resource,arg);

    
    // int ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &pms->sched);
    // if (ret != 0) {
    //     perror("pthread_setschedparam");
    //     exit(-1);
    // }
    sched_setscheduler(pthread_self(), SCHED_FIFO,&pms->sched);//SCHED_FIFO//SCHED_RR(round-robin)
    pthread_mutex_lock(&mtx);
    while(start == 0){
        pthread_cond_wait(&cond,&mtx);
    }
    pthread_mutex_unlock(&mtx);
    DEBUG_INFO("start thread = %d",pms->index);
    pthread_attr_getschedparam(&pms->attr,&pms->sched);
    DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
    
    while(1){
        for(int i = 0;i < 10000;i++){
            //pthread_testcancel();
            for(int j = 0;j < 10000;j++){counter++;}
        }
        break;
    }
    DEBUG_INFO("index = %d",pms->index);
    while(1)sleep(1);
    return 0;
    pthread_cleanup_pop(0);
}

void sig_func(int signo){
    auto it = pthread_list.begin();
    DEBUG_INFO("%lu",pthread_list.size());
    for(;it != pthread_list.end();it++){
        
        pthread_cancel(*it);
    }
    DEBUG_INFO("good bye");
    sleep(2);
    std::cout << "counter = " << counter << std::endl;
    exit(0);
}

int main(int argc, char**){
    sighandler sig_ret;
    sig_ret = signal(SIGINT, sig_func);
    if(sig_ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    DEBUG_INFO("pid = %u",getpid());
    for(int i=0; i < 10; i++){
        pthread_t t;
        struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
        if(!pms){
            perror("malloc");
            raise(SIGINT);
            while(1)sleep(1);
        }
        pms->index = i;       

        pthread_attr_init(&pms->attr);
        pthread_attr_getschedparam(&pms->attr,&pms->sched);
        DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
        pthread_attr_setschedpolicy(&pms->attr,SCHED_FIFO);//SCHED_OTHER);//SCHED_RP);//SCHED_FIFO);
        pms->sched.sched_priority = 100 - (i + 1)*5;
        pthread_attr_setschedparam(&pms->attr,&pms->sched);

        pthread_attr_getschedparam(&pms->attr,&pms->sched);
        DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);

        
        int ret = pthread_create(&t, NULL, func,pms);
        if(ret != 0){
            perror("malloc");
            raise(SIGINT);
            free(pms);            
            
        }
    }
    start = 1;
    //pthread_cond_signal(&cond);
    pthread_cond_broadcast(&cond);
    while(1){
        sleep(1);
    }
    return 0;
}

测试结果略

 小结

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

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

相关文章

Kubernetes_容器网络_01_Docker网络原理(二)

文章目录 一、前言二、被隔离的Docker容器三、网桥Bridge四、VethPair网络对五、统一宿主机上的两个Container容器通信六、宿主机访问其上的容器七、宿主机上的容器访问另一个宿主机八、尾声 一、前言 二、被隔离的Docker容器 Linux 网络&#xff0c;就包括&#xff1a;网卡&…

技术选型对比- RPC(Feign VS Dubbo)

协议 Dubbo 支持多传输协议: Dubbo、Rmi、http,可灵活配置。默认的Dubbo协议&#xff1a;利用Netty&#xff0c;TCP传输&#xff0c;单一、异步、长连接&#xff0c;适合数据量小(传送数据小&#xff0c;不然影响带宽&#xff0c;响应速度)、高并发和服务提供者远远少于消费者…

UnityWebGL+阿里云服务器+Apache完成项目搭建展示

一、服务器相关 Step1:租借一台阿里云服务器 我自己租借了一台北京的ECS服务器&#xff0c;有免费一年的活动&#xff0c;1 vCPU 2 GiB&#xff0c;我自己选择的Ubuntu系统&#xff0c;也可以选择Windows系统 Step2:进入远程连接 进入自己的服务器实例后&#xff0c;点击远程…

vue+elementui+nodejs机票航空飞机航班查询与推荐

语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode )本系统主要是为旅客提供更为便利的机票预定方式&#xff0c;同时提高民航的预定机票的工作效率。通过网络平台实现信息化和网络化&am…

关于Android的性能优化,主要是针对哪些方面的问题进行优化

前言 我们在开发Android的时候&#xff0c;经常会遇到一些性能问题&#xff1b;例如&#xff1a;卡顿、无响应&#xff0c;崩溃等&#xff0c;当然&#xff0c;这些问题为我们可以从日志来进行追踪&#xff0c;尽可能避免此类问题的发生&#xff0c;要解决这些问题&#xff0c…

mysql从零开始(05)----锁

全局锁 使用 # 启用全局锁 flush tables with read lock # 释放全局锁 unlock tables开启全局锁后&#xff0c;整个数据库就处于只读状态了&#xff0c;这种状态下&#xff0c;对数据的增删改操作、对表结构的更改操作都会被阻塞。 另外&#xff0c;当会话断开&#xff0c;全…

【1015. 可被 K 整除的最小整数】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给定正整数 k &#xff0c;你需要找出可以被 k 整除的、仅包含数字 1 的最 小 正整数 n 的长度。 返回 n 的长度。如果不存在这样的 n &#xff0c;就返回 -1。 注意&#xff1a; n 不符合 64 位带…

手把手教你在winform中将文本或文件路径拖到控件中

文章目录 前言博主履历介绍&#xff1a;一、将txt文件的所有内容复制到 RichTextBox中二、将txt文件的一行内容移动到RichTextBox中三、将多个文件的全路径复制到 RichTextBox中四 、源码1、[Winform从入门到精通&#xff08;1&#xff09;——&#xff08;如何年入30万&#x…

「MIAOYUN」:降本增效,赋能传统企业数字化云原生转型 | 36kr 项目精选

作为新经济综合服务平台第一品牌&#xff0c;36氪自2019年落地四川站以来&#xff0c;不断通过新锐、深度的商业报道&#xff0c;陪跑、支持四川的新经济产业。通过挖掘本土优质项目&#xff0c;36氪四川帮助企业链接更多资源&#xff0c;助力企业成长&#xff0c;促进行业发展…

分布式系统概念和设计——命名服务设计和落地经验

分布式系统概念和设计 通过命名服务&#xff0c;客户进程可以根据名字获取资源或对象的地址等属性。 被命名的实体可以是多种类型&#xff0c;并且可由不同的服务管理。 命名服务 命名是一个分布式系统中的非常基础的问题&#xff0c;名字在分布式系统中代表了广泛的资源&#…

C语言:指针求解鸡兔同笼问题

题目&#xff1a;鸡兔同笼问题 要求&#xff1a;使用自定义函数void calc(int h, int f,int *c,int *r) 求解鸡兔同笼问题。 h 表示总的头数&#xff0c;f 表示总的脚数。 例子&#xff1a; 输入&#xff1a; 5 16 输出&#xff1a; 2 3 分析&#xff1a; 在该代码中&a…

05-Docker安装Mysql、Redis、Tomcat

Docker 安装 Mysql 以安装 Mysql 5.7为例&#xff1a; docker pull mysql:5.7Mysql 单机 Mysql 5.7安装 启动 Mysql 容器&#xff0c;并配置容器卷映射&#xff1a; docker run -d -p 3306:3306 \--privilegedtrue \-v /app/mysql/log:/var/log/mysql \-v /app/mysql/data:…

ASP.NET Core MVC 从入门到精通之文件上传

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

VMware NSX-T Data Center 3.2.2.1 - 数据中心网络全栈虚拟化

请访问原文链接&#xff1a;https://sysin.org/blog/vmware-nsx-t-3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org VMware NSX-T Data Center 3.2.2.1 | 30 MAR 2023 | Build 21487560 VMware NSX-T Data Center 3.2.2 | 08 …

NOA上车「清一色」自主品牌,哪些供应商正在突围前线

随着入门级L2进入普及周期&#xff0c;以NOA&#xff08;高速、城区&#xff09;为代表的L2/L2赛道&#xff0c;正在成为主机厂、硬件供应商、算法及软件方案商的下一波市场制高点的争夺阵地。 高工智能汽车研究院监测数据显示&#xff0c;2023年1-3月中国市场&#xff08;不含…

MySQL基础(十六)变量、流程控制与游标

1. 变量 在MySQL数据库的存储过程和函数中&#xff0c;可以使用变量来存储查询或计算的中间结果数据&#xff0c;或者输出最终的结果数据。 在 MySQL 数据库中&#xff0c;变量分为系统变量以及用户自定义变量。 1.1 系统变量 1.1.1 系统变量分类 变量由系统定义&#xff…

【Nacos在derby模式下密码忘记】使用derby的ij工具重置密码/修改密码

【问题描述】 nacos部署未用mysql,直接运行&#xff0c;使用了默认的derby数据库&#xff0c;这时候不一小心修改的密码给忘记了&#xff0c;无法登录 当时是部署在centos上的一个演示环境&#xff0c;没有采用mysql数据库&#xff0c;如果生产上&#xff0c;建议使用mysql。 …

php用户分享信息技术交流大学生论坛系统vue

系统应实现的目标 1. 提供安全、友好的操作环境&#xff1a;避免一些网上的不良言论&#xff0c;创造一个和谐的网络环境。 2. 提供发表帖子功能&#xff1a;注册的用户可以自由发帖&#xff0c;发表符合法律法规的言论。 3. 提供回复帖子功能&#xff1a;户可以自由回复&am…

camunda执行监听器如何使用

在Camunda工作流引擎中&#xff0c;执行监听器是一种机制&#xff0c;用于在业务流程执行期间捕获特定事件并执行相应的操作。它们可以帮助您实现一些重要的任务&#xff0c;例如&#xff1a; 1、记录或更新业务数据&#xff1a;当流程中的任务或事件发生时&#xff0c;您可以…

工程监测无线中继采集发送仪 指示灯功能说明及接口定义

工程监测NLM5无线中继采集发送仪 指示灯功能说明及接口定义 指示灯功能说明 标识 名称 状态 描述说明 备注说明 CHG 正在充电 常亮 正在充电 DON 充电完成 常亮 已充满 POW 电源指示 常亮 外部电源已连接 仅用于指示是否连接了外部电源 熄灭 无外部电源 SIG 空 RUN 运行状态 闪…