ClickHouse JSON 函数用法

ClickHouse 支持的JSON函数 SELECT name FROM system.functions WHERE name LIKE '%JSON%' ; -- 1.判断JSON是否合法 SELECT isValidJSON('{"a":1}') as isValid; ┌─isValid─┐ │ 1 │ └──────┘ --2. 判断JSON是否存在某个值 select JSONHas('{"a": "hello", "b": [-100, 200.0, 300]}', 'b') exist ; ┌─exist─┐ │ 1 │ └─────┘ -- 3.JSON 返回值的类型 SELECT JSONType('{"a": "hello", "b": [-100, 200.0, 300]}', 'a') AS a_type, JSONType('{"a": "hello", "b": [-100, 200.0, 300]}', 'b') AS b_type; ┌─a_type─┬─b_type─┐ │ String │ Array │ └──────┴───────┘ --4.JSON 对象长度

YARN调度器【capacity-scheduler.xml】默认配置

Hadoop版本:3.1.3 1、三种常见调度器1.1、先进先出调度器1.2、容量调度器1.3、公平调度器 2、容量调度器 多队列配置3、单词4、默认配置【capacity-scheduler.xml】 1、三种常见调度器 1.1、先进先出调度器 first-in first-out schedulerFIFO Scheduler后入队的任务 要等待 前入队的任务 出队 可配置: 1、每个用户的最大资源占比,防止单个用户把资源占满 2、限制哪些用户可以提交应用到本队列 1.2、容量调度器 Capacity Scheduler相当于 多个 FIFO Scheduler不同队列上的任务可以并行(比如 3个队列就可以并行3个任务)相同队列上的任务不能并行 可配置: 1、默认容量占比:各个队列占据一定百分比的资源 (如:a队列40% b队列60%) 2、最大容量占比:队列占据的资源百分比的最大值 (如:a队列最大70%,当超出40%时,可以借b队列的空闲资源,最多借30%) 划分方式: 按业务划分(更常用):下单、支付、物流… 按技术划分:HIVE、Spark、Flink… 1.3、公平调度器 Fair Scheduler和Capacity Scheduler类似,可以多队列配置;不同的是,叶子队列不是FIFO的在同一条叶子队列上,所有作业可以并发; 资源分配的依据:时间尺度、优先级、资源缺额… 在时间尺度上获得公平的资源 最大最小公平分配算法 2、容量调度器 多队列配置 1、编辑配置文件 vim $HADOOP_HOME/etc/hadoop/capacity-scheduler.xml 2、修改根队列下面的叶队列名称,逗号分隔(此处新增队列名称为hive) <property> <name>yarn.scheduler.capacity.root.queues</name> <value>default,hive</value> <description>在根队列下设置叶队列名称</description> </property> 3、修改 名为default的队列 的容量占比 <property> <name>yarn.scheduler.capacity.root.default.capacity</name> <value>40</value> <description>设置root下名为default队列的容量占比</description> </property> 4、给新队列配置 <property> <name>yarn.scheduler.capacity.root.hive.capacity</name> <value>60</value> <description>root下名为hive的队列 的 容量占比</description> </property> <property> <name>yarn.scheduler.capacity.root.hive.user-limit-factor</name> <value>1</value> <description>每个用户可以占据该队列资源占比的上限(防止某用户把资源占满)</description> </property> <property> <name>yarn.

C++设计模式--Prototype 原型模式 和 Builder 构建器

“对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。 典型模式 •Factory Method •Abstract Factory •Prototype •Builder 1. Prototype 原型模式 动机(Motivation) 在软件系统中,经常面临着“某些结构复杂的对象"的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。如何应对这种变化?如何向“客户程序(使用这些对象的程序) "隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序"不随着需求改变而改变? 代码示例 首先看一下工厂模式的代码 //抽象类 class ISplitter{ public: virtual void split()=0; virtual ~ISplitter(){} }; //工厂基类 class SplitterFactory{ public: virtual ISplitter* CreateSplitter()=0; virtual ~SplitterFactory(){} }; 将两个类合并,将CreateSplitter函数重命名为Clone函数,得到代码如下 //抽象类 class ISplitter{ public: virtual void split()=0; virtual ISplitter* clone()=0; //通过克隆自己来创建对象 virtual ~ISplitter(){} }; //具体类 class BinarySplitter : public ISplitter{ public: virtual ISplitter* clone(){ return new BinarySplitter(*this); // 通过拷贝构造函数创建对象 } }; class TxtSplitter: public ISplitter{ public: virtual ISplitter* clone(){ return new TxtSplitter(*this); } }; class PictureSplitter: public ISplitter{ public: virtual ISplitter* clone(){ return new PictureSplitter(*this); } }; class MainForm : public Form { ISplitter* prototype;//原型对象 public: MainForm(ISplitter* prototype){ this->prototype=prototype; } void Button1_Click(){ ISplitter * splitter= prototype->clone(); //克隆原型得到一个新对象 splitter->split(); } }; 模式定义

用VSCode开发Python工程

入门Python Python的优缺点优点缺点 VSCode软件准备Python第三方库安装VSCode配置Python相关创建项目配置工作区配置启动项 VSCode插件开发 python 时报错 Python的优缺点 优点 开源免费,解释型语言跨平台,可扩展性强简单易用,学习成本低,看起来非常优雅干净标准库和第三库众多,开发的时间短,胶水语言 缺点 运行速度慢(解释型语言的通病)(对于个人来说,比手动快就OK,而且有些应用场景可以容忍速度慢)代码加密困难(对于普通人来说,仅用于提高效率,便捷生活,并不需要加密) VSCode VScode是一个相当优秀的IDE,具备开源、跨平台、模块化、插件丰富、轻量化、启动时间快、颜值高的特质 软件准备 下载地址如下: Python:https://www.python.org/downloads/ VSCode:https://code.visualstudio.com/ Python推荐Python3最新版本即可 具体的安装教程,请自行搜索查阅(Python安装要记得勾选添加环境变量) Python第三方库安装 首先检查下python是否安装成功 1、打开cmd,输入python,点击回车。 2、退出、输入pip list,检查第三库安装信息(安装默认自带的库) 安装第三方的包 通过python自带的pip工具,配置VScode需要的常用的库 flake8和yapf flake8会检查编写代码时的不规范的地方和语法错误。 yapf是一个代码格式化工具,可以一键美化代码。 安装过程如下: 1、在cmd输入pip list检查是否已存在需要的包 2、输入pip install flake8下载安装flake8 3、输入pip install yapf下载安装yapf VSCode配置Python相关 安装python插件 1、打开VScode,按下快捷键Ctrl+Shift+X,进入插件管理页面。 2、在搜索栏输入python。 3、选择插件,点击安装。 (因为我已经安装了,所以显示的是禁用/卸载) 安装中文插件 按下快捷键Ctrl+Shift+P,输入config, 选择 configure Display Language,然后选择zh-cn,重启 创建项目 创建一个本地文件夹,作为项目文件 配置工作区 1、点击设置图标,打开设置界面 2、选择工作区,配置工作区文件 settings.json 配置flake8和yapf并关闭pylint工具。 在工作区域输入以下内容: { "python.linting.flake8Enabled": true, "python.formatting.provider": "yapf", "python.linting.flake8Args": ["--max-line-length=248"], "python.linting.pylintEnabled": false } 配置启动项 创建py文件,输入print(“Hello World”)

C++设计模式--Factory Method工厂方法和抽象工厂方法

“对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。 典型模式 •Factory Method •Abstract Factory •Prototype •Builder 1. Factory Method工厂方法 动机(Motivation) 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合? class FileSplitter { //... void split(){ //... } }; class MainForm : public Form { //... public: void Button1_Click(){ string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); FileSplitter* splitter = new FileSplitter(); //应该声明为抽象类,而不是具体的类型 splitter->split(); } }; 在上面代码中,实现了文件分割器。一个类型,要看到未来变化的需求。这是就要做抽象类,即面向接口的编程。一个对象的类型,往往应该声明为抽象类或者接口,而不应该声明成具体的类。如果声明为具体类型,就定死了,不能应对未来的变化。 假设还要支持文本分割TxtSplitter()、图片分割PictureSplitter()等等。抽象出一个基类ISplitter()。 class ISplitter{ // 抽象基类 public: virtual void split()=0; virtual ~ISplitter(){} }; class BinarySplitter : public ISplitter{ }; class TxtSplitter: public ISplitter{ }; class PictureSplitter: public ISplitter{ }; class MainForm : public Form { TextBox* txtFilePath; TextBox* txtFileNumber; ProgressBar* progressBar; public: void Button1_Click(){ //.

可重入锁简单理解

可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。 synchronized 和 ReentrantLock 都是可重入锁。 可重入锁的意义之一在于防止死锁。 实现原理实现是通过为每个锁关联一个请求计数器和一个占有它的线程。当计数为0时,认为锁是未被占有的;线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数器置为1 。 如果同一个线程再次请求这个锁,计数器将递增; 每次占用线程退出同步块,计数器值将递减。直到计数器为0,锁被释放。 可重入锁指的是在一个线程中可以多次获取同一把锁,比如: 一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法,而无需重新获得锁;

C++设计模式--Bridge 桥模式

单一职责”模式: 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。 典型模式 • Decorator • Bridge 1. Bridge 桥模式 动机(Motivation) 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度? 代码示例 class Messager{ public: virtual void Login(string username, string password)=0; virtual void SendMessage(string message)=0; virtual void SendPicture(Image image)=0; virtual void PlaySound()=0; // 播放声音 virtual void DrawShape()=0; // 画图像 virtual void WriteText()=0; // 写文本 virtual void Connect()=0; // 连接网络 virtual ~Messager(){} }; //平台实现 class PCMessagerBase : public Messager{ //PC平台 public: virtual void PlaySound(){ //********** } virtual void DrawShape(){ //********** } virtual void WriteText(){ //********** } virtual void Connect(){ //********** } }; class MobileMessagerBase : public Messager{ //Mobile平台 public: virtual void PlaySound(){ //========== } virtual void DrawShape(){ //========== } virtual void WriteText(){ //========== } virtual void Connect(){ //========== } }; //业务抽象 class PCMessagerLite : public PCMessagerBase { // PC平台精简版 public: virtual void Login(string username, string password){ PCMessagerBase::Connect(); //.

最好用的coreldraw2020中文版,安装好后不显示评估版,显示已注册

​CorelDRAW Graphics Suite是加拿大Corel公司的平面设计软件 CorelDRAW Graphics Suite非凡的设计能力广泛地应用于商标设计、标志制作、模型绘制、插图描画、排版及分色输出等等诸多领域。作为一个强大的绘图软件,它被喜爱的程度可用事实说明:用作商业设计和美术设计的PC机几乎都安装了 。 CorelDRAW让您轻松应对创意图形设计项目。市场领先的文件兼容性以及高质量的内容可帮助您将创意变为专业作品:从与众不同的徽标和标志到引人注目的营销材料以及令人赏心悦目的Web图形,应有尽有。 CorelDRAW界面设计友好,空间广阔,操作精微细致。它提供了设计者一整套的绘图工具包括圆形、矩形、多边形、方格、螺旋线,等等,并配合塑形工具,对各种基本以作出更多的变化,如圆角矩形,弧、扇形、星形等。同时也提供了特殊笔刷如压力笔、书写笔、喷洒器等,以便充分地利用电脑处理信息量大,随机控制能力高的特点。 coreldraw2020中文版,目前看来这个最好用了。 具体下载地址见:https://mp.weixin.qq.com/s/e-rumQ66ZYe69iFd2C9p1w

Python——字符串的拼接

字符串的拼接:名字的组成 将两个不同的字符串,拼接形成一个字符串,并将新字符串输出来。字符串或串(String)是由数字、字母、下划线组成的一串字符。在 Python 中,字符串用单引号或者双引号括起来。在很多情况下,我们需要将两个字符串拼接起来,形成一个字符串。 例如,一个人的姓名,通常是由“姓氏”+“名字”组成的。在很多程序中,为了方便后续处理,通常将姓氏和名字分别存在两个变量中。然后在显示时,要将姓氏和名字拼接起来,按全名显示。 first_name = 'Zhang' last_name = 'san' 输出如下: full_name = 'Zhang san' 相关知识 Python 中使用+来合并两个字符串,这种合并字符串的方法叫做拼接。其基本语法如下: result_string = source_string1 + source_string2 其中: source_string1:待合并的第一个字符串; source_string2:待合并的第二个字符串; result_string:合并后的字符串。 注意:如果需要,在两个字符串之间可以增加相应的空格,具体见下面的例子。例如,将姓氏和名字拼接成全名: # coding=utf-8 # 将姓氏和名字分别保存在两个变量中 first_name = 'Zhang' last_name = 'san' # 将姓氏和名字拼接,将结果存储在full_name变量中 full_name = first_name + " " + last_name print(full_name) 输出结果: Zhang san 编程要求 实现如下功能: 1.将存放姓氏的字符串变量和存放名字的字符串变量拼接起来 中间用一个空格隔开,并将结果存储在full_name变量中; 2.打印输出full_name变量。 测试说明 测试输入: Hu dong 预期输出: Hu dong 上代码: 如果注释理解有误,请大佬们多多评论指教!!

常用数据结构与经典算法 简单讲解与示例代码

数据结构与算法 数据结构与算法是一个学习计算机绕不过去的话题,而我们大学之中多数课程之中都使用伪代码进行讲解,给对我们的学习理解也是一把双刃剑,虽然可以让我们自己通过算法、思路自己写出程序,但也可能“一叶障目”致使我们迟迟不知道具体到程序语言上问题出在哪里 所以我想自己使用不同的程序设计语言编写简单的数据结构和讲解一些经典的算法,在复习和记录的过程之中也和大家一起交流讨论数据结构与算法的一些巧妙的设计和个人见解与跳过的“坑”,各位共勉。 帖子会慢慢更新,当然速度可能不太能保证,也可能在后续的更新之中调整文章结构。 常用数据结构 数据结构与算法线性表线性表简介线性表示例代码单链表实例 学生信息链表 循环链表循环链表简介循环链表示例代码 静态链表静态链表简介静态链表示例代码 双向链表双向链表简介双向链表示例代码 栈(stack)又名堆栈栈简介栈示例代码链式栈 示例代码 经典算法——递归与回溯汉诺塔八皇后问题 数据结构相关问题维吉尼亚密码表魔术师发牌问题约瑟夫问题后缀表达式 线性表 线性表简介 定义 线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。 优点 线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。 特征 1.集合中必存在唯一的一个“第一元素”。 2.集合中必存在唯一的一个 “最后元素” 。 3.除最后一个元素之外,均有唯一的后继。 4.除第一个元素之外,均有唯一的前驱。 线性表示例代码 代码(C语言) 链式线性表 Visual Studio 2019 /** * 数据结构 C语言链式线性表 * @FileName SingleLinkList.c * @author W.Lionel.Esaka */ #include <stdio.h> #include <stdlib.h> typedef int DataType; #define Status int; #define CORRECT 1; #define ERROR 0; #define OVERFLOW -1; /*单链表的类型定义如下*/ typedef struct node{ DataType data; struct node* next; } LinkNode, * LinkList; /*创建指定长度单链表 尾插法*/ void CreateListTail(LinkList* list, int Number) { LinkList node, r; int i; srand(time(0)); *list = (LinkList*)malloc(sizeof(LinkList)); r = *list; for (i = 0; i < Number; i++) { node = (LinkNode*)malloc(sizeof(LinkNode)); node->data = rand() % 100 + 1; r->next = node; r = node; } r->next = NULL; } /* 插入元素 */ Status InsertLinkList(LinkList* list, int position, DataType value) { int i = 1; LinkList p, s; p = *list; while (p && i < position) { p = p->next; i++; } if ( !

cocos2dx 3.17.2 集成 FairyGUI【将c++代码加进项目】(2)

1:参考资料 https://www.jianshu.com/p/547e584e05d8 https://www.cnblogs.com/whj0402/p/12034412.html 2:主流程 1.复制libfairygui到frameworks\cocos2d-x\cocos\editor-support\fairygui 2.在VS中添加libfairygui库,右键解决方案/添加/现有项目。 有报错,这个是为了构建fairgui例子工程设置的路径,手动改下路径也可以 实际地址:E:\cocos\FightSystem\frameworks\cocos2d-x\cocos\2d 修改为对应路径即可 添加库依赖 编译成功,绑定lua测试下先

C++面向对象的编程-练习3(学生成绩设置与输出,静态数据成员的运用)

声明一个Student类,在该类中包括一个数据成员:score(代表课程成绩)、两个静态数据成员:total_score(代表总分),count(代表学生总人数)。成员函数有:构造函数、析构函数、account(int)用于设置分数、静态成员函数sum()返回所有学生的总成绩、静态成员函数average()返回所有学生的平均成绩、print()用于打印当前学生对象的成绩等。在主程序中,输入某班同学的成绩,并调用上述函数打印全班同学的成绩、求出全班学生的成绩之和与平均分等。 · #include<iostream> using namespace std; class Student { public: Student(int);// 构造函数 ~Student();// 析构函数 void account(int);// 设置分数 static int sum();// 返回总成绩 static double average();// 返回平均成绩 void print();// 打印输出Student的相关信息 private: int score;// 分数 static int total_score;// 定义静态数据成员总分 static int count;// 定义静态数据成员总人数 }; Student::Student(int sco)// 构造函数 { score = sco; total_score = total_score + score; count++; } Student::~Student()// 析构函数 { cout << "成绩为:" << score <<" "; } void Student::account(int sco) { score = sco; total_score = total_score-score+sco; } int Student::sum() { return total_score; } double Student::average() { double a; a = (double)total_score / count; return a; } void Student::print() { cout << "

cocos2dx 3.17.2 集成 FairyGUI【构建FairyGUI例子项目】(1)

1:参考资料 cmake构建项目 https://blog.csdn.net/gaoshou_zgt/article/details/104144340/ 官方文档: https://fairygui.com/docs/sdk/cocos2dx https://github.com/fairygui/FairyGUI-cocos2dx 2:构建cocos2dx例子项目 参展上图的项目结构 运行成功 3:问题 官方新增了个3D装载器,这里编译不过注释先

windows下RabbitMQ安装后,无法进入web管理页面问题

问题: 安装RabbitMQ后无法访问http://localhost:15672/ 无法进入UI管理界面 解决办法 查看UI管理界面插件是否开启? 1、在cmd窗口下进入rabbitmq安装目录下的sbin目录,使用rabbitmq-plugins.bat list查看已安装的插件列表。 2、使用rabbitmq-plugins.bat enable rabbitmq_management开启网页管理界面 3、在浏览器中输入http://127.0.0.1:15672/ 输入用户名和密码(默认为guest) 到这完成了后台管理页面功能的开启。 更多编程支持,请关注我的公众号《coder练习生》

js获取当前URL、域名、端口号等

属性值举例结果href完整的URLhttp://localhost:8080/project/front/user/serviceIndex?type=1protocol协议http:hostname主机名localhostport端口号8080host主机名+端口号localhost:8080pathname当前 URL 的相对路径 /project/front/user/serviceIndex search当前 URL 的参数?type=1hash#开始的锚 获取方法,如:window.location.hostname,得:localhost 转发来自:js获取当前URL、域名、端口号等

罗技Ghub一直初始化/打不开的解决办法

当罗技Ghub一直初始化时,看网上说的原因是因为它想更新,但是国内没有服务器,所以一直循环。 治标的解决办法就是,首先,关掉lghub,包括后台。 然后点击第四个lghub_updater.exe 当然,你打不开它,但是稍等一下,你再去开启lghub.exe,你就会发现,打开了! 亲测了3次有效。 治本的解决办法还没发现,发现了再更新

call、apply、bind的用法

一个案例明白call(),apply(),bind()的用于以及区别 <script> var [name,age] =['张洪伟','17'] var obj = { nikename:'小张同学', yourage:this.age, //17 do:function(girl,play){ console.log(this.nikename + '的年龄是'+this.age+'喜欢'+girl +"和" +play) } } console.log(obj.nikename) console.log(obj.yourage) //指向全局this window // obj.do()// // bind() apply() call()都可以用来改变this指向 var obj2 = { nikename:'小宏同学', age:18, like:'耍帅' } obj.do.call(obj2); //小宏同学的年龄是18 obj.do.apply(obj2) //小宏同学的年龄是18 obj.do.bind(obj2)() //小宏同学的年龄是18 // 1.call() apply() bind() 都可以改变this指向 但是 bind() 绑定的意思() obj.do.call(obj2,'漂亮女孩','打游戏'); obj.do.apply(obj2,['大眼睛的女孩','打王者']) // call和apply的区别 call接受单个参数, , , apply接受数组 obj.do.bind(obj2,'女生','吃')() // bind接受单个参数,,, </script>

[GO] golang 中main包下入口文件调用其它go文件函数出现undefined

golang main包下推荐只有一个main.go的入口文件 当有其他的go文件 , 并且在其他go文件中定义了函数 在main.go入口文件中调用了该函数 , 执行go run main.go , 会提示undefined 如果非得这样做那么go run 的时候把所有文件都得加上 , 否则默认只加载main.go这一个文件 只有非main包里的文件才会通过依赖去自动加载。所以你需要输入多个文件作为参数 应该使用go run a.go b.go c.go 或 go run *.go来运行,编译同理

自动跳转http://www.veryyx.com nginx配置

server { listen 80; server_name www.abcd.com abcd.com; rewrite ^(.*)$ https://$host$1 permanent; location / { index index.html index.htm; } } server { listen 443 ssl; server_name www.veryyx.cn abcd.com; #ssl on; ssl_certificate /usr/local/nginx/conf/3749980_www.abcd.com_nginx/3749980_www.abcd.com.pem; ssl_certificate_key /usr/local/nginx/conf/3749980_www.abcd.com_nginx/3749980_www.abcd.com.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; if ($http_host !~ '^www\.abcd\.com$') { rewrite ^(.*) https://www.abcd.com$1 redirect; } root /home/www/wwwroot/abcd/public; index index.html index.htm index.php; include enable-php.conf; location / { #try_files $uri $uri/ /index.php?$query_string; try_files $uri $uri/ /index.

C++设计模式--Decorator 装饰模式

“单一职责”模式: 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。 典型模式 • Decorator • Bridge 1. Decorator 装饰模式 动机(Motivation) 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低? 代码示例 流操作,有内存流,网络流,文件流;也有各种各样的操作:读,写,定位,加密 //业务操作 class Stream{ //基类 public: virtual char Read(int number)=0; virtual void Seek(int position)=0; virtual void Write(char data)=0; virtual ~Stream(){} }; //主体类 class FileStream: public Stream{ // 文件流 public: virtual char Read(int number){ //读文件流 } virtual void Seek(int position){ //定位文件流 } virtual void Write(char data){ //写文件流 } }; class NetworkStream :public Stream{ // 网络流 public: virtual char Read(int number){ //读网络流 } virtual void Seek(int position){ //定位网络流 } virtual void Write(char data){ //写网络流 } }; class MemoryStream :public Stream{ // 内存流 public: virtual char Read(int number){ //读内存流 } virtual void Seek(int position){ //定位内存流 } virtual void Write(char data){ //写内存流 } }; //扩展操作,加密文件流,读,写,定位操作前后进行加密操作 class CryptoFileStream :public FileStream{ // 继承文件流 public: virtual char Read(int number){ //额外的加密操作.

【RocketMQ】学习RocketMQ必须要知道的主从同步原理

本文主要参考《RocketMQ技术内幕》和《RocketMQ实战与原理分析》两本书,​以及RocketMQ 4.8.0的源码,作为学习的记录 RocketMQ的Broker分为Master和Slave两个角色,为了保证高可用性(HA), Master角色的机器接收到消息后,要把内容同步到Slave机器上,这样一旦Master宕机,Slave机器依然可以提供服务。 下面介绍Master和Slave角色机器间同步功能实现的源码。 同步元数据 ​ Slave需要和Master同步的不只是消息本身,一些元数据信息也需要同步,比如TopicConfig信息、ConsumerOffset信息、DelayOffset和SubscriptionGroupConfig信息。 元数据的同步操作是由Slave发起的,定时从Master获取,核心代码如下: private void handleSlaveSynchronize(BrokerRole role) { if (role == BrokerRole.SLAVE) { if (null != slaveSyncFuture) { slaveSyncFuture.cancel(false); } this.slaveSynchronize.setMasterAddr(null); slaveSyncFuture = this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { BrokerController.this.slaveSynchronize.syncAll(); } catch (Throwable e) { log.error("ScheduledTask SlaveSynchronize syncAll error.", e); } } }, 1000 * 3, 1000 * 10, TimeUnit.MILLISECONDS); } else { //handle the slave synchronise if (null !

C++设计模式--Strategy 策略模式 和 Observer 观察者模式

“组件协作”模式: 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。 典型模式 • Template Method • Strategy • Observer / Event 1. Strategy 策略模式 动机( Motivation) 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担(有的算法代码几乎不用,却要装到缓存中)。 如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题? 代码示例 税的计算,有许多国家。刚开始支持CN,US,DE,后来由于业务需求变化,需要添加另一些国家,例如法国FR 第一种做法,利用枚举类型实现。如果要添加法国的税法计算方法,则需要改变代码,在源代码中添加新的代码。违背了开放封闭原则(对扩展开放,对更改封闭),类模块应该尽可能以扩展的方式应对未来的变化,而不是找到源代码并修改源代码这种方式应对变化。改源代码,需要重现编译,测试,部署,代价高。 enum TaxBase { CN_Tax, US_Tax, DE_Tax, FR_Tax //更改 }; class SalesOrder{ TaxBase tax; public: double CalculateTax(){ //... if (tax == CN_Tax){ //CN*********** } else if (tax == US_Tax){ //US*********** } else if (tax == DE_Tax){ //DE*********** } else if (tax == FR_Tax){ //更改 //... } //.... } }; 第二种方式。创建一个TaxStrategy基类,各国的作为子类。在SalesOrder类中,使用工厂模式为多态指针创建具体的子类对象,具体的创建由StrategyFactory决定。

Python ValueError: File is not a recognized excel file

Python读取Excel类文件错误 我是在pandas读取xlsx文件时遇到的错误 ValueError: File is not a recognized excel file ValueError:文件不是可识别的excel文件 这个错误的原因是xlsx文件本身的问题,可能是wps或是Excel保存格式出错无法被识别。 之后重新制作xlsx文件并完整保存 ImportError: Missing optional dependency 'xlrd'. Install xlrd >= 1.0.0 for Excel support Use pip or conda to install xlrd. ImportError:缺少可选依赖项“xlrd”。安装xlrd>=1.0.0 for Excel支持使用pip或conda安装xlrd。 这里又出现了新问题,缺少xlrd,pip 安装 xlrd 模块即可 pip install xlrd 如果安装的是2.0以下版本的xlrd模块,此次的读取问题应该已经解决了。 但是如果安装的xlrd版本超过2.0,依旧会有错误 ValueError: Your version of xlrd is 2.0.1. In xlrd >= 2.0, only the xls format is supported. Install openpyxl instead. ValueError:您的xlrd版本是2.0.1。在xlrd>=2.0中,仅支持xls格式。改为安装openpyxl。 这里的问题是由于xlrd2.0以上版本仅支持xls格式Excel,pip 安装 openpyxl 模块即可

标题Ant Design of Vue 组件库中Modal“确认“按钮和“取消“按钮成英文状态

标题Ant Design of Vue 组件库中Modal"确认"按钮和"取消"按钮成英文状态 因为是国际化的原因,造成确定按钮和取消按钮变成英文,需要设置 okText 与 cancelText 以自定义按钮文字。 <div> <a-modal v-model="visible" title="功能模块配置" @ok="handleOk" ok-text="确认" cancel-text="取消"> <p>Some contents...</p> <p>Some contents...</p> <p>Some contents...</p> <p>Some contents...</p> </a-modal> </div> 我找了很多原因,但是,通过我百度发现,都是清一色设置本地解析为zh-CN,在vue中我设置了,但是不起作用,我又把index.html中的语言设置成lang="zh-CN"还是不起作用,我有又看了API结合之前百度到的关键字眼国际化又找到Modal中的国际化,果然,惊喜就在眼前,美滋滋。。。。。。。。雄起,奥利给!!!!!! 设置之前: 设置之后:

流动粒子(flow01001)

流动粒子(flow01001) 示例HTMLCSSJS 更多有趣示例 尽在知屋安砖社区 示例 HTML <script id="vertexShader_particle" type="x-shader/x-vertex"> attribute vec3 a_position; attribute vec3 a_particle; attribute vec2 a_reference; uniform float u_time; uniform mat4 u_m_model; uniform mat4 u_m_view; uniform mat4 u_m_MVP; uniform mat4 u_m_proj; uniform sampler2D b_position; uniform sampler2D b_velocity; varying vec3 v_colour; varying float v_fogDepth; varying float v_opacity; float random(vec2 st) { return fract(sin(dot(st, vec2(12.9898,78.233)))* 43758.5453123); } vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.

万字长文,38 图爆肝 Redis 基础!

00 前言 Redis 在互联网技术存储方面的使用可以说是非常广泛了,只要是接触过 Java 开发的朋友就算你没用过,都会听过它。在面试也是非常高频的一个知识点。 最近,我的的小弟小胖和老王就对 Redis 非常感兴趣;我推荐它一本书《Redis设计与实现》。谁知这货说看不下去,非要我来总结一波。所以本文算是给小胖和老王的学习资料,也是我自己的学习笔记。希望对你有帮助。 还是老规矩,先上张脑图。全文 13274 字,从下午 2 点爆肝到晚上 9 点,先上张思维导图镇楼: 0.1 往期精彩 1、小胖问我:select 语句是怎么执行的? 2、女朋友问我:MySQL 索引的原理是怎样的? 3、小胖问我:MySQL 日志到底有啥用? 4、老王问我:MySQL 事务与 MVCC 原理是怎样的? 5、女朋友问我:MySQL 的锁机制是怎样的? 01 什么是 Redis? 官方是这么描述的: Redis (用 C 语言实现的)是一个开源的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。 信息简洁明了,一下就知道了三个点:基于内存、用作缓存、多种数据结构。 的了,那就从这三个方面开始研究呗。 1.0 为什么要用 Redis 做缓存? 上面说了,用作缓存。有些小伙伴可能会问:有 MySQL 数据库就得了呗?干嘛还要缓存?而且为啥要用 Redis 做?Map 不行嘛? 第一、二个问题,都知道 MySQL 数据是存在磁盘的,而 CPU 访问磁盘是非常慢的。如果遇到并发高的时候,所有线程每次都要访问磁盘,估计得挂。 到底有多慢?请看链接:zhuanlan.zhihu.com/p/24726196 Redis 和 Map 做下对比,就知道为啥不合适了。 Map 是本地缓存,如果在多台机器部署,必须每个机器都要复制一份,否则造成缓存不一致;Redis 是分布式缓存,部署在多台机器,也是用的同一份缓存,保持了一致性,问题不大。Map 做缓存,数据量大的话会导致 JVM 内存飙升,进而拖垮程序,并且 JVM 挂了,还会导致数据丢失;Redis 可以用更大容量的内存(看你的配置,即几十G都没问题)做缓存,并且还可以持久化到磁盘。 02 Redis 的数据结构 你可能第一反应不就 “String(字符串)、List(列表)、Hash(哈希)、Set(集合)和 Sorted Set(有序集合)么?”,太简单了,我都会。

详解GCN的性质

前言 本文参考 – 深入浅出图神经网络 GNN 原理解析一书 GCN 的性质 GCN 与 CNN 的联系 1. 图像是一种特殊的图数据 在图像中如果将像素视作节点,将像素之间空间坐标的连线作为彼此之间的边,如此图像数据就变成了一种结构非常规则的图数据,CNN 中的卷积计算则是用来出来这类固定的 2D 栅格结构的图数据。相较之下,一般意义下的图数据,往往单个节点附近的邻域结构是千差万别的,数据之间的关系也较为复杂多样,GCN中的卷积计算则是用来处理更普遍的非结构化的图数据。 2.从网络连接方式来看,两者都是局部连接 在 GCN 中的计算方式是每次图卷积操作作用范围是当前节点的一节子图,对于 CNN 来说针对于不同大小的卷积核,计算范围是当前节点的固定大小的 n × n n \times n n×n 的栅格内的像素。这种节点下一层的特征计算只依赖于自身领域的方式,在网络连接上表现为一种局部连接的结构。 3.两者的卷积核的权重是处处共享的 与 CNN 一样,GCN 的卷积核也作用于全图的所有节点,在每个节点处的计算中权重参数是共享的,这样的处理方式大大减少了单层网络的参数量,可以有效避免过拟合的现象出现。 4.从模型层面看,感受域随着卷积层的增加而变大 对于 CNN 来说,随着层数增多,所包含的信息来源于更广泛的临近像素点,对于 GCN 来说,层数加深表明信息的来源于更高阶的子图结构。 GCN 对图结构数据进行端到端的学习 图数据中同时包含着两部分信息:属性信息与结构信息。属性信息描述了图中对象的固有性质;结构信息描述了对象之间的关联性质,这种关联所产生的结构不仅对图数据中节点的刻画具有很大的帮助作用,而且对全图的刻画也非常关键。一个优秀的针对图数据的学习系统,必须能够做到对属性信息和结构信息进行端到端的学习。 在此之前,介绍两种非常典型的图数据学习方式 – 基于手工特征和基于随机游走。 一般来说,图数据中的属性信息的处理是比较简单的,按照属性的类型进行相应的编码设计,然后将其拼接成一个表示节点属性的特征向量就可以了,但是结构信息蕴含在节点之间的关系中,是比较难处理的。上述的两种方法核心都在于如何处理图的结构信息上。 基于手工特征:该方法对于图数据的处理方式依赖于人工干预,具体来说,将图中节点的结构信息以一些图的统计特征进行代替,常见的有节点的度、节点的中心度、节点的 PageRank 值等,然后将这个代表节点结构信息的特征向量与代表节点属性信息的特征向量拼接在一起,送到下游任务中进行学习。这种方法的最大问题在于,表示结构信息的特征向量需要人为定义,因此很难确定这些统计特征是否对学习后面的任务有效。 基于随机游走 其基本思想是将图中节点所满足的关系与结构的性质映射到一个新的向量空间中,比如在图中距离更近的两个节点,在新的向量空间中的距离也更近。通过这样的优化目标即将图里面的数据转化成向量空间中的数据,这样处理起来更加方便。 该方法和基于手工特征的方法的思路一样,将代表节点的结构信息的特征向量和属性信息的向量进行拼接,然后进行下游的任务学习。所不同的是,其节点的结构信息是通过随机游走类方法进行学习的,并不依赖人为定义,因此相比之下会更加高效。 GCN 方法可以完成对结构信息和属性信息的端到端的学习。其核心在于计算公式上: L ~ s y m X W \mathbf{\widetilde{L}_{sym}XW} L sym​XW,这一计算过程可以分解成两步: W X \mathbf{WX} WX 是对属性信息的仿射变换,学习了属性特征之间的交互模式。 L ~ s y m X W \mathbf{\widetilde{L}_{sym}XW} L sym​XW从空域来看是聚合邻居节点的过程,代表了对节点局部结构信息的编码。 在这里引入一个很重要的概念:图同构问题(graph isomorphism problem),即给定两个图,判断这两个图是否是完全等价的。具体描述为:假设有两个图 H = ( V H , E H ) H=(V_H,E_H) H=(VH​,EH​) 和图 G = ( V , E ) G=(V,E) G=(V,E) 子图 同构即从 H H H 到 G G G 存在这样一个函数 f : V H → V f:V_H \rightarrow V f:VH​→V 并且 ( u , v ) ∈ E H (u,v)\in E_H (u,v)∈EH​ 使得 ( f ( u ) , f ( v ) ) ∈ E (f(u),f(v))\in E (f(u),f(v))∈E 同样成立, f f f 叫做子图同构的一个映射。

详解图信号处理与图卷积神经网络

前言 本文参考 – 深入浅出图神经网络 GNN 原理解析一书 图信号处理 图信号处理(Graph Signal Processing ,GSP)是离散信号处理(Discrete Signal Processing,DSP)理论在图信号领域的应用。其通过傅里叶变换、滤波等信号处理基本概念的迁移,来研究对图信号的压缩、变换、重构等信号处理的基础任务。 图信号与图的拉普拉斯矩阵 图信号 给定图 G ( V , E ) G(V,E) G(V,E),其中 V V V 表示图中的节点集合,图信号是一种描述从节点域到实数域的映射,表示成向量的形式为: x = [ x 1 , x 2 , … , x N ] T \mathbf{x}=[x_1,x_2,\dots,x_N]^T x=[x1​,x2​,…,xN​]T,其中 x i x_i xi​ 表示的是节点 v i v_i vi​ 上的信号强度。与离散时间时间信号不同,图信号是定义在节点上的信号,节点之间有自己固有的关联结构,在研究图信号的性质的时候,除了要考虑图信号的强度之外,还要考虑图的拓扑结构,不同图上同一强度的信号,具有截然不同的性质 在大多数任务中,图信号指的就是图中节点的特征矩阵 图的拉普拉斯矩阵 拉普拉斯矩阵(Laplacian Matrix)是用来研究图的结构性质的核心对象,拉普拉斯矩阵的定义如下: L = D − A \mathbf{L=D-A} L=D−A,其中 D i i = ∑ j A i j \mathbf{D}_{ii}=\sum_j\mathbf{A}_{ij} Dii​=∑j​Aij​ 是由节点的度组成的对角矩阵。对应的 A \mathbf{A} A 就代表图的邻接矩阵。在实际应用中常用的是对称归一化拉普拉斯矩阵,定义为: L s y m = D − 1 2 L D − 1 2 \mathbf{L_{sym}=D^{-\frac{1}{2}}LD^{-\frac{1}{2}}} Lsym​=D−21​LD−21​

C++设计模式--模板方法

组件协作”模式: 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。 典型模式 • Template Method • Observer / Event • Strategy Template Method 动机( Motivation) 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。 如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求? 在这个方式,蓝色的调用红色的,也就是应用程序开发人员的代码调用程序库开发人员的代码 //程序库开发人员开发1、3、5三个步骤 class Library{ public: void Step1(){ //... } void Step3(){ //... } void Step5(){ //... } }; //应用程序开发人员开发2、4步骤和程序主流程 class Application{ public: bool Step2(){ //... } void Step4(){ //... } }; int main() { Library lib(); Application app(); lib.Step1(); if (app.Step2()){ lib.Step3(); } for (int i = 0; i < 4; i++){ app.

对于Spring Cloud Feign入门示例的一点思考

原文地址 blog.csdn.net Spring Cloud Feign Spring Cloud Feign 是一套基于 Netflix Feign 实现的声明式服务调用客户端。它使得编写 Web 服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它既可完成对 Web 服务接口的绑定。它具备可插拔的注解支持,包括 Feign 注解、JAX-RS 注解。它也支持可插拔的编码器和解码器。Spring Cloud Feign 还扩展了对 Spring MVC 注解的支持,同时还整合了 Ribbon 和 Eureka 来提供均衡负载的 HTTP 客户端实现。 分布式应用早在十几年前就开始出现,各自的应用运行在各自的 tomcat,jboss 一类的容器中,他们之间的相互调用变成了一种远程调用,而实现远程调用的方式很多。按照协议划分,可以有 RPC,Webservice,http。不同的框架也对他们有了各自的实现,如 dubbo(x),motan 就都是 RPC 框架,本文所要讲解的 Feign 便可以理解为一种 http 框架,用于分布式服务之间通过 Http 进行接口交互。说他是框架,有点过了,可以理解为一个 http 工具,只不过在 spring cloud 全家桶的体系中,它比 httpclient,okhttp,retrofit 这些 http 工具都要强大的多。 入门 先用一个简单的例子,看看如何在项目中使用 Feign。示例项目使用 maven 多 module 构建,采用 springcloud 的 Dalston.SR1 版本 <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.

以 zookeeper 为注册中心搭建 spring cloud 环境

原文地址 www.jianshu.com 在 spring cloud 体系中,有多种手段实现注册中心,本例中采用 zookeeper 作为注册中心的角色。服务提供者向 zookeeper 注册,服务消费者从 zookeeper 中发现服务提供者的相关信息,从而远程调用服务提供方。 服务提供者 引入相关依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> </dependency> <!-- 热部署工具 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> spring cloud 与 zookeeper 的集成主要依赖 spring-cloud-starter-zookeeper-discovery 模块 定义 DTO 对象 public class UserDTO { private Long id; private String name; private Date birthday; /* 省略getter,setter方法 */ } 定义服务提供接口 @RestController public class ComputeController { @Autowired private DiscoveryClient client; @RequestMapping(value = "

[Spring Cloud] Eureka 的自我保护模式及相关问题

原文地址 blog.csdn.net 一 Eureka 的自我保护模式 等待 Eureka Server 自动恢复重启 Eureka Server关闭 Eureka 的自我保护模式 二开发环境的 Eureka Server三参考链接 一、Eureka 的自我保护模式 访问Eureka主页时,如果看到这样一段大红色的句子: EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE. 那么就表明着Eureka的 自我保护模式 (self-preservation mode) 被启动了,当 Eureka Server 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁的启动关闭客户端),那么这个节点就会进入自我保护模式,一旦进入到该模式,Eureka server 就会保护服务注册表中的信息,不再删除服务注册表中的数据(即不会注销任何微服务),当网络故障恢复后,该 Ereaka Server 节点就会自动退出自我保护模式(我的 Eureka Server 已经几个月了,至今未自动退出该模式) 默认情况下,如果 Ereaka Server 在一段时间内没有接受到某个微服务示例的心跳,便会注销该实例(默认 90 秒),而一旦进入自我保护模式,那么即使你关闭了指定实例,仍然会发现该 Ereaka Server 的注册实例中会存在被关闭的实例信息,如果你对该实例做了负载均衡,那么仅关闭了其中一个实例,则通过网关调用接口api时很可能会发生如下异常:

迁移软件:如何迁移程序到其他盘?

有时候我们使用电脑时会觉得很卡,绝大部分人的操作都是打开360安全卫士/电脑管家等软件,进行垃圾文件清理,优化加速,但是这种情况治标不治本,尤其是对于某些快要存满的C盘来说,大部分的数据都是一些应用程序产生的。那么问题来了,如何迁移程序到其他盘,释放C盘空间呢? 前段时间小编发现了一款比较好用的可以迁移应用程序到其他盘的软件——易我电脑迁移,帮我迁移了不少C盘的软件走,顿时C盘空间就解放了不少。下面给大家分享一下易我电脑迁移软件迁移应用程序到其他盘的过程: 步骤1.启动易我电脑迁移程序,在主页上选择“应用搬家”,然后点击“开始”。 步骤2.勾选需要迁移的应用程序,并选择要迁移到的目标分区,然后点击“迁移”继续。 步骤3.完成迁移。 注意: ◆迁移完成后,需要重新启动计算机以刷新所有迁移的程序。 易我电脑迁移是一款实用的数据迁移软件,适用于Windows 10/8.1/8/7/Vista/XP系统,界面简约,功能强大且操作简单。支持在两台电脑之间传输数据,不仅能将旧电脑的文件/文件夹迁移到新电脑,还能将旧电脑上的应用程序和Windows账号也一并迁移,而无需在新电脑上重新安装和设置,大大节约了用户的时间;软件还提供备份和还原功能,备份电脑上的程序、文件和账号,避免因数据意外丢失而带来的损失,同时,备份的生成的镜像文件还支持在另一台电脑上进行还原,起到迁移数据的作用;易我电脑迁移还能将空间不足的磁盘上的应用程序迁移到其他分区或磁盘,释放磁盘空间;还可以通过连接旧电脑的磁盘,将无法正常工作的旧电脑中的应用和数据完整迁移出来;除此之外,软件还提供系统盘瘦身、大文件清理以及应用管理功能,帮助用户更好地管理磁盘数据。点击下载>> 希望本文能帮助到大家哦!

你还在用 select * 吗

在企业进行开发中不可能不和数据库打交道,而目前大部分公司用的数据库都是关系型数据库MYSQL。那么写SQL语句也就会成为我们工作中必不可少的一部分。当数据库表中的数据量比较小时可能看不出来不同SQL语句的区别,但当数据量比较大时,就可以感受到不同SQL语句执行速度的快慢。所以今天就给大家普及一下关于一些数据库的优化。 当知道有几条查询结果时,请使用"LIMIT" 加上LIMIT可以限制SQL语句返回的条数,比如"LIMIT 1",这样就是返回1条数据结果,如果你已经知道该结果只有一条,就可以加上,因为这样写代表找到了一条就立马返回,避免了全表扫描。 在建表时给字段选择合适的数据类型和长度 不同的数据类型和长度占用的磁盘和内存大小是不同的,所以针对我们要存储的数据选择一个合适的数据类型和长度可以节省我们的存储空间,也能够提高我们后续查找数据的效率。 当你只需要一些列时,不要使用"SELECT *" "SELECT *"是会查找表中所有的列,是对全表进行扫描的,而如果只需要一些列名就只查该列名就行。 给你经常使用的where字句的列加上索引 当你经常需要根据一个列名来查询表的数据时,建议给该列加上索引,这样查找速度相比原来就要快非常多。不过一个表不要建太多索引,索引太多会降低表的性能。 以上就是关于一些数据库的调优比较常见的几种方法,当然,关于数据库的知识可博大精深着呢,这只是九牛一毛。如果大家有兴趣,后面再给大家慢慢普及。

Qt release 应用程序无法正常启动(0xc000007b)

release 编译之后生成的.exe文件 单击出现下图所示错误,这种情况考虑缺少.dll文件 首先在网上根据大神的指导 尝试使用 windeployqt 工具命令 无效...换了个思路 然后找到高级系统设置 对path进行检查 发现忘记添加D:\Qt\Qt5.9.6\5.9.6\msvc2015_64\bin (根据自己的实际使用的情况进行添加) 添加之后点击之前生成的.exe文件,成功运行

DBUtils介绍

1 DBUtils简介 DBUtils是Apache Commons组件中的一员,开源免费! DBUtils是对JDBC的简单封装,但是它还是被很多公司使用! jar:commons-dbutils.jar 2 DBUtils主要类 DbUtils:都是静态方法,一系列的close()方法; QueryRunner: update():执行insert、update、delete;DDL、DML * int update(String sql, Object… params) --> 可执行增、删、改语句 * int update(Connection con, String sql, Object… parmas) 可以支持事务的功能 query():执行select语句;DQL * T query(String sql, ResultSetHandler rsh, Object… params) --> 可执行查询 > 它会先得到ResultSet,然后调用rsh的handle()把rs转换成需要的类型! * T query(Connection con, String sql, ResultSetHadler rsh, Object… params),支持事务 batch():执行批处理。 增、删、改 public void fun1() throws SQLException { QueryRunner qr = new QueryRunner(); String sql = “insert into user values(?

小记-Java保留两位小数-使用BigDecimal

参考自:https://www.cnblogs.com/limin12891/p/11116680.html及jdk1.8文档如下例: double a = 1; double b = 3; BigDecimal num1 = new BigDecimal("" + a); BigDecimal num2 = new BigDecimal("" + b); // 四舍五入保留两位小数 BigDecimal result1 = num1.divide(num2, 2, BigDecimal.ROUND_HALF_UP); // 保留3位小数 BigDecimal result2 = num1.divide(num1, 3, BigDecimal.ROUND_HALF_UP); System.out.println(result1); System.out.println(result2); 其中divide的第三个参数用于设定保留的规则: ROUND_HALF_UP即:四舍五入 还有其它可设定值: 值含义ROUND_DOWN向零方向舍入––ROUND_UP向远离0的方向舍入––ROUND_CEILING向正无穷方向舍入––ROUND_FLOOR向负无穷方向舍入––ROUND_HALF_DOWN相当于五舍六入––ROUND_HALF_EVEN不展开描述––ROUND_UNNECESSARY不需要舍入模式 (无尽报错)––

numpy练习笔记

习题来源:https://cloud.tencent.com/developer/inventory/514 1.如何用0来填充一个数组的边界? z= np.ones((10, 10)) z= np.pad(z, pad_width=1, mode='constant', constant_values=0) print (z) [[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0.] [0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0.] [0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0.] [0. 1. 1. 1. 1. 1. 1. 1. 1. 1.

(学习笔记)树莓派4B使用usb转串口通讯模块

一.写在前面 首先,树莓派上自带一个串口,用于连接蓝牙或是串口命令行,对于这个串口的使用我们已经简单探究过了,可以点击蓝字看看我的这篇文章:树莓派4B和pc之间进行串口通信(解决报错). 但是,对于嵌入式的应用来说串口设备很多,需要的串口数量也很多,自带的一个串口满足不了我们的需求了,所以通过USB外接串口就很有用处了。 树莓派官方的系统已经集成了USB转串口驱动,可以直接连接上串口就可以使用。 好,废话不多了,进入主题。 二.简单检查一下 把usb转串口通讯模块插上 ls -l /dev/tty* #查看识别的串口号 stty -F /dev/ttyUSB0 #查看串口的波特率 dmesg | grep ttyUSB0 #查看串口的连接信息 树莓派默认安装了python 和 pyserial, 使用pip命令查看一下有没有 命令行输入pip list(这里说一下,输入pip list 和 pip3 list ,显示的库数量不一样,在这里不展开说,有兴趣的朋友可以自己搜素一下。) python -m serial.tools.list_ports #命令python查看安装到系统上的串口 好了,我们的检查就到这里,后面最常用的还是第一个命令,我再贴一次 ls -l /dev/tty* #查看识别的串口号 三.举个例子说一下 光说不练假把式,我们来自我验证一下。 把USB转串口的TX和RX引脚用杜邦线短接一下,来测试一下能不能用。 测试代码: python3 import serial ser = serial.Serial('/dev/ttyUSB0',115200,timeout = 0.5) ser.isOpen() ser.write('123456'.encode()) ser.inWaiting() ser.read(6) 这里提一下,因为树莓派4B自带python2 和 python3,你输入python的话,用的就是python2.7 上面的测试代码中写入格式要改一下,这里为什么要改,挖个坑,以后来具体说说。没啥事的话两个都输入试一下。 #使用python2 ser.write('123456') 四.USB转串口模块和minicom串口助手 首先,在命令行界面输入 sudo minicom -D /dev/ttyUSB0 -b 9600 好了,能用了,minicom和pc的简单通信参考一下这个博客(树莓派4B和pc之间进行串口通信(解决报错)),简单不多说了。

4-1-2数组定义

#include <stdio.h> #include <stdlib.h> int main() { //数组是数据的集合1-100 //数组的数据是同类型的1-100都是整数,不能1 1.2 2 2.3 //数组地址是连续的 int array[100]; //1.没有初始化的数组,仅仅申请了100个整数的内存空间. int array2[3]={1,2,3}; //2.有初始化的数组,完整初始化,该数组申请了三个整数内存空间,并赋值三个数1,2,3 int array3[100]={1,2,3}; //3.有初始化的数组,不完整初始化,该数组申请了100个整数内存空间,并只赋值三个数1,2,3 放在数组的前面。[1,2,3,0,0,0,0,0,0,0,…0] int n; scanf("%d\n",&n); int array4[n]; //实际应用当中无报错,可使用,但是在一些所谓的教材中,认定为非法! //当我们学会指针的时候,就可以完成抛弃这种定义,用指针思维来做. system("pause"); return 0; }

微信小程序基于wx-charts的canvas组件横向滚动

在微信小程序里插入折线图,可以使用wx-charts,在绘制到canvas上。 wx-charts具体用法就不介绍了。折线图显示后,却发现了一个问题:数据x轴长度不确定,导致如果数据很长的话,数据就会挤在一起,如果长度较大,canvas能滚动就好了。 在网页中,我们直接设置父元素固定宽度,子元素宽度超过父元素,让父元素overflow:auto;就行了,可是对微信小程序的canvas组件不起作用。 第一时间想到scroll-view组件,但是scroll-view组件不能作为canvas的父元素。但是 研究发现,虽然canvas不会响应scroll-view的滚动,但是bindscroll事件方法是有返回值的,e.detail里有个scrollLeft参数,是随滚动不断变化的, 一、wxml部分 二、css部分 三、js部分 四、结果 当数据较少时,canvas会全屏展示,不能滚动,当数据较多时,可以左右滚动。 不足之处:1、因为canvas的滚动是在滑动结束,获取到scrollLeft值之后的操作,所以滚动很生硬,不流畅; 2、不能使用wx-charts内置方法touchHandler。

小程序组件中监听父组件传来的properties值

前提: 在小程序中,子组件需要接受父组件传来的2个值A和B,子组件需要同时根据A和B做一些业务处理。 通常,我们可以在properties单独的针对A和B进行监听,但是我们发现,有时候在A中使用B,取不到B值,或在B中使用A,取不到A值。这是为什么呢?其实这个涉及到js事件循环和小程序监听数据的知识。 上图为例: 父组件传入两个值campstatus和isIndex,campstatus为动态数据,isIndex为静态值2。 1、由于campstatus是异步数据,第一次能监听到campstatus的默认值0和isIndex的值2 2、当父组件campstatus数据变为1的时候,子组件能监听到campstatus值发生了变化,但是isIndex的值没有发生变化,所以无法进入isIndex的observer方法里执行相关的业务逻辑。 那么,有没有同时能监测到这两个值的方法呢?所以针对子组件需要同时根据A和B做一些业务处理的情况,我们需要同时监听这两个值变化。只要有一个值发生变化,都会重新处理相关业务。 参考微信开发文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/observer.html

Vue实战笔记(二) 引入Element Plus

Element Plus 是为适配 Vue3 而对 Element UI 进行重构后产生的前端组件库,包含丰富的基础组件 下面先贴出 官方文档,里面的介绍已经十分全面和详细,大家遇到的很多问题都可以在上面找到答案 假设现在我们已经用 vue-cli 4 工具创建了一个 Vue3 项目,然后怎么在项目中引入 Element Plus 呢? 注意,这里必须是用 vue-cli 4 创建的 Vue3 项目,否则后面会报错,首先介绍一下默认生成的目录结构 + demo + node_modules(存放第三方模块) + public(存放静态文件) - favicon.ico(图标) - index.html (页面模板) + src(我们自己写的文件一般放在这个文件夹下) + assets(存放资源文件) + components(存放公共组件) + router.js(路由管理:Router) + store.js (状态管理:Vuex) + views(存放视图组件) - App.vue(页面入口文件) - main.js(程序入口文件) - package.json(项目配置文件) - package-lock.json(项目配置文件) - babel.config.js(babel 配置文件) - README.md(项目说明文档) - ...(其它配置文件) 1、安装 Element Plus npm 是 Node 的包管理工具,我们可以通过 npm 安装 Element Plus

stm32 cubemx freertos 中断二值信号量卡死问题

功能: 按键中断里面释放二值信号量, 然后点亮LED灯 问题: 卡在xSemaphoreGiveFromISR 代码: void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ uint32_t ulReturn; BaseType_t pxHigherPriorityTaskWoken; /* 进入临界段,临界段可以嵌套 */ ulReturn = taskENTER_CRITICAL_FROM_ISR(); if(GPIO_Pin == KEY1_Pin){ BaseType_t pxHigherPriorityTaskWoken; xSemaphoreGiveFromISR(BinarySem_Handle,&pxHigherPriorityTaskWoken); //释放二值信号量 //如果需要的话进行一次任务切换 portYIELD_FROM_ISR(pxHigherPriorityTaskWoken); } /* 退出临界段 */ taskEXIT_CRITICAL_FROM_ISR( ulReturn ); } static void LED_Task(void* parameter) { BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */ uint32_t r_queue; /* 定义一个接收消息的变量 */ while (1) { //获取二值信号量 xSemaphore,没获取到则一直等待 xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */ portMAX_DELAY); /* 等待时间 */ if(pdPASS == xReturn) { printf("

Pytest测试框架(七):pytest 的setup/teardown方法

setup() 和 teardown() 方法用于初始化和清理测试环境,可以保证测试用例的独立性。 pytest的setup/teardown方法包括: 模块级别(setup_module/teardown_module)、 函数级别(setup_function/teardown_function)、 类级别(setup_class/ teardown_class)、 方法级别(setup_method/teardown_methond或者setup/teardown)。 pytest中有四只种setup和teardown: 1、setup_module和teardown_module在整个测试用例所在的文件中所有的方法运行前和运行后运行,只会运行一次; 2、setup_class和teardown_class则在整个文件中的一次class中所有用例的前后运行; 3、setup_method和teardown_method在class内的每个方法运行前后运行; 4、setup_function和teardown_function则是在非class下属的每个测试方法的前后运行; 模块级别 模块中的第一个测试用例开始前执行setup_module方法,模块中的最后一个测试用例结束后运行teardown_module方法。 import pytest def setup_module(): print("初始化。。。") def teardown_module(): print("清理。。。") class Test_Demo(): def test_case1(self): print("开始执行测试用例1") assert 1 + 1 == 2 def test_case2(self): print("开始执行测试用例2") assert 2 + 8 == 10 def test_case3(self): print("开始执行测试用例3") assert 99 + 1 == 100 结果: 模块初始化。。。 PASSED [ 33%]开始执行测试用例1 PASSED [ 66%]开始执行测试用例2 PASSED [100%]开始执行测试用例3 模块清理。。。 函数级别 setup_function/teardown_function在每个测试函数前后运行,只对函数用例生效,不在类中。 import pytest def setup_function(): print("

ICP和NDT匹配算法精度、速度和鲁棒性对比

注意:如下实验是针对里程计任务而进行的,默认是帧间匹配,而对于帧到局部地图匹配情况下的长时间下的轨迹精度对比,请参考我的这篇博客: 【附优化方法的ICP源码】ICP与NDT匹配算法精度对比,以及手动实现的ICP和基于优化方法的ICP精度对比 1.实验条件 前提:以下ICP与NDT算法均使用的是PCL 1.8库中提供的实现方法,它们可以设置的参数较多,这里只探讨那些最常用的参数。 数据:杭州海创园区的室外点云数据,其效果如下: 后续点云的匹配,均以该点云为基础,对其增加平移、旋转,来模拟各种不同的状态,以观察ICP和NDT的匹配效果。 匹配结果优异的判定条件: 对于平移的判定采用欧氏距离来判断,欧氏距离越接近0,表示匹配的结果越优;对于旋转的判定,难以直接采用某个距离范数表示,下文将通过相对旋转矩阵的对角矩阵是否更接近单位阵来做简单判定,或者直接通过变换之后的效果观察判定。 2.实验 实验时,会将两帧关键帧点云分别平移和旋转一定的数值,然后对比icp和ndt对匹配结果的精度(fitness,欧式距离)、用时,以及目测效果。 由于该实验是为了验证室外里程计情况下的匹配结果,所以所有实验均是围绕这个主题进行。里程计前后两帧角度相差较小,位移也较小。实验时以等步长的方式对点云施加平移和旋转。 对于icp和ndt的匹配,均使用一个单位矩阵作为位姿的预测,不给任何先验。 2.1 平移 实际里程计推算情况下,前后两帧点云多数情况下只在x方向产生平移差距,所以后续关于平移的比对只针对x方向。 所用参数: icp.setMaximumIterations(30); icp.setTransformationEpsilon(1e-3); icp.setMaxCorrespondenceDistance(1.0); ndt.setMaximumIterations(30); ndt.setTransformationEpsilon(1e-3); ndt.setStepSize(0.01); ndt.setResolution(1.0); 第一组实验:两帧点云之间只在x方向差了0.1米 实际效果 匹配效果 以下但凡是两张图片并排排列的情形,左边那张是icp的效果,右边那张是ndt的效果 icp use time(s): 0.072361 distance: 0.0558645 fitness: 0.117922 R 0.999977 0.0067574 -0.000550125 -0.00675799 0.999977 -0.00104073 0.000543081 0.00104442 1 ndt use time(s): 0.571204 distance: 0.0728875 fitness: 0.116304 R 0.999925 0.0119963 -0.00228154 -0.0119934 0.999927 0.00124959 0.00229637 -0.00122213 0.999997 第二组实验:两帧点云之间只在x方向差了0.5米 实际效果 匹配效果: icp use time(s): 0.

趣味搜索框(Bouncy Castle Form)

趣味搜索框(Bouncy Castle Form) 示例HTMLCSSJS 更多有趣示例 尽在知屋安砖社区 示例 HTML <div id="wrap"> <form id="bounce" autocomplete="off"> <input type="email" id="email" maxlength='25' required/> <input type="submit" id="submit" value="SIGN UP"/> </form> <div id="fakeform"> <p id="wrapper"> <span class="cursor"></span> </p> </div> <svg id='bouncehouse' viewbox='0 0 1000 800'> <defs> <marker id="cap" markerheight="20" markerwidth="20" refx="70" refy="40" orient="auto-start-reverse" viewbox="0 0 800 800"> <g transform="rotate(90,90,90), translate(0,50)"> <g> <path d="M 60 60 Q 40 70 20 60 Q 10 40 20 20 Q 40 10 60 20 Q 70 40 60 60 "

烟圈(smoke ring)

烟圈(smoke ring) 示例HTMLCSSJS 更多有趣示例 尽在知屋安砖社区 示例 HTML <div class="app"> <canvas id="c"></canvas> <svg id="s" viewBox="0 0 600 600" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" stroke="#fff" fill="none"> <defs> <mask id="m1"> <rect fill="#fff" width="100%" height="100%"/> <circle fill="#000" cx="300" cy="300" r="285"/> </mask> <mask id="m2"> <rect fill="#fff" width="100%" height="100%"/> <circle fill="#000" cx="300" cy="300" r="272"/> </mask> </defs> <circle class="ring1" cx="300" cy="300" r="210" stroke-width="220" stroke="#000" /> <g id="marks"> <path mask="url(#m1)" opacity="0.5" d="M0.2,289.5l599.6,20.9 M6.6,237.6l586.9,124.7 M21.8,187.6l556.3,224.8 M45.6,141l508.8,318 M77.1,99.3 L300,300 M115.3,63.6L300,300 M300,300L159.2,35.1 M207.

Linux的进程管理

目录 1、概述 2、进程描述符 2.1 进程描述符的分配 2.2 进程描述符的存放 2.3 进程状态 2.4 进程上下文 2.5 进程家族树 3、进程的创建 4、进程的终结 5、线程的实现 1、概述 进程是执行期的代码。但是进程不止包括这样一段可执行的代码,还包括进程执行相关的各种资源: 打开的文件;挂起的信号;内核内部的数据;处理器状态;一个或多个具有内存映射的地址空间;一个或多个执行线程;存放全局变量的数据段;...... 进程在创建它的时候开始存活,在Linux系统中,这通常的fork()系统调用的结果。fork()系统调用通过复制一个现有进程来创建一个新的进程,调用fork()的进程称为父进程,新创建的进程称为子进程。在fork()系统调用结束时,父进程恢复执行,子进程开始执行。fork()系统调用从内核返回两次:一次是回到父进程,一次是回到子进程。Linux内核中,fork()实际上是通过clone()调用实现的。 fork()调用后,通过exec()调用可以创建新的地址空间,并把程序载入其中。最终,程序通过exit()调用退出执行,并释放其占用的资源。父进程可以通过wait4()调用等待子进程的执行结果。程序执行完成后被设置为僵死状态,直到它的父进程调用wait()或waitpid()调用。 执行线程简称线程,是在进程中活动的对象。每个线程都有一个独立的程序计数器、进程栈和一组进程寄存器。内核调度的对象是线程而不是进程。对于Linux而言,线程就是一种特殊的进程。 2、进程描述符 进程描述符用来描述一个具体的进程的所有信息。进程描述符的数据结构叫做task_struct,定义在<linux/sched.h>文件中。 task_struct数据大小约为1.7KB(32位机器),包含了内核管理一个进程所需要的全部信息: 进程的id(pid);打开的文件;进程的地址空间;挂起的信息;进程的状态;...... 2.1 进程描述符的分配 Linux通过slab分配器动态分配task_struct结构,分配时只需要在进程内核栈的尾端创建一个新的结构thread_info即可。其中,task域存放的是指向task_struct的指针。 2.2 进程描述符的存放 内核通过唯一的进程标识值PID(Process Identification Value)来标识每个进程。pid的类型是隐含类型pid_t,实际上就是int。为了兼容老版本,PID数的最大值是32768(有符号short int最大值),但是可以在<linux/threads.h>中增加到400万。内核把每个进程的pid存放到进程描述符中。 内核大部分处理进程的操作,都是通过task_struct实现的,因此内核需要能获取到指向task_struct的指针。有些内存结构有专门的寄存器存放task_struct的指针,而x86等寄存器不富裕的体系,只能在内核栈的尾端创建thread_info,通过计算内存偏移来简接查找task_struct。 2.3 进程状态 进程描述符的state域描述了进程的状态。进程包含5种状态: TASK_RUNNING:运行,进程是可执行的。可能正在执行,也可能正在任务队列等待执行。这是进程在用户空间中执行的唯一可能的状态;TASK_INTERRUPTIBLE:可中断,此时的进程正在睡眠(也叫阻塞),等待某些条件的达成。处于此状态的进程会因为提前接收到信号而被唤醒;TASK_UNINTERRUPTIBLE:不可中断,除了接收到信号也不会提前被唤醒,其他的和可中断相同。这个状态通常用在等待时不受干扰,或者等待的事情很快发生的场景;__TASK_TRACED:被其他进程跟踪的进程,例如通过ptrace对调试进程进行跟踪;__TASK_STOPPED:停止,进程停止执行,进程没有投入运行,也不能投入运行。通常这种状态发生在接收到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU等信号时;在调试期间接受到任何信号,也会进入这个状态。 2.4 进程上下文 当一个程序执行了系统调用,或者触发了某个异常,就陷入了内核空间,此时称内核“代表程序执行”,并处于进程上下文。除非期间有更高优先级的进程要执行,并且调度器做出了相应调整,否则在内核退出的时候,程序恢复在用户空间继续运行。 系统调用和异常处理是对内核明确定义的接口,进程只有通过这些接口才能陷入内核,即进程对内核的所有访问都需要通过这些接口。 2.5 进程家族树 Linux的所有进程都是PID为1的初始进程的后代。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本,并执行相关的程序,最终完成系统启动的整个过程。 系统中每个进程都有一个父进程,和零个或多个子进程。拥有同一父进程的进程,称为兄弟进程。进程间的关系存放在进程描述符中,每个task_struct都包含一个parent指针,指向父进程所在的task_struct,以及一个名为children的指针链表,指向所有的子进程的task_struct。 3、进程的创建 Unix把进程的创建拆分成了两个函数: fork():Linux通过clone()系统调用实现了fork(),通过拷贝当前进程创建一个子进程。子进程和父进程的区别只在于PID、PPID(父进程的PID)和一些统计量。exec():将可执行文件载入地址空间开始执行。 Linux的fork()使用写时拷贝(copy-on-write)页实现资源的复制。资源的复制,只有在需要写入的时候才进行,在此之前以只读方式共享。这种技术使地址空间的页拷贝推迟到实际发生写入的时候才进行,如果页根本不会被写入,例如fork()后立即执行exec(),则无需复制。这样可以避免拷贝大量根本不会被使用的数据,这也是Unix快速执行的能力的一种重要支撑。 fork()的实际开销就是复制父进程的页表,以及给子进程创建唯一的进程描述符。进程页表是进程私有的结果,映射了内核态和用户态的线性地址。 4、进程的终结 当一个进程终结时,内核会回收进程的全部资源,并通知父进程。 1、do_exit()方法回收资源并更新状态: 回收地址空间:如果没有其他进程占用,就释放掉地址空间;回收文件描述符、文件系统数据:引用计数分别递减,如果减为0,就释放;执行退出代码:执行操作系统规定的退出动作,并把退出代码存放到task_struct中的exit_code中供父进程随时检索;设置退出状态:task_struct中的exit_state设置为EXIT_ZOMBIE,进程不再接受调度;给子进程重新寻找父进程,新的父进程是线程组的其他线程,或者init进程;调用schedule()方法切换到新的进程。 2、此时,进程所占有的内存资源只剩下内核栈、thread_info和task_struct。此时进程存在的唯一目的,就是向它的父进程提供信息。父进程检索到相关信息后,或者通知内核那是无关信息后,内核会释放剩下的这些资源。 5、线程的实现 Linux内核并没有线程的概念,它把线程当做进程来实现,线程仅仅被视为与其他进程共享某些资源的进程。线程有自己的task_struct,所以从内核的角度,线程只是一个普通的进程,仅仅是和其他进程共享了一些资源,比如地址空间等。 1、线程的创建 创建线程和创建进程相似,也是调用clone()实现,只不过传递的一些参数,用来控制共享一些资源: clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0) 这些代码是用来和父进程共享:地址空间、文件系统资源、文件描述符和信号处理程序。