架构师系列- 定时任务(四)- XXl-Job

XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展,其中“XXL”是主要作者,大众点评许雪里名字的缩写

和ElasticJob的区别
相同点
  • E-Job和X-job都有普遍的用户基础和完整的技术文档,都能满足定时任务的基本功能需求
不同点
  • X-Job 侧重的业务实现的简单和管理的方便,学习成本简单,失败策略和路由策略丰富,推荐使用在“用户基数相对少,服务器数量在一定范围内”的情景下使用
  • E-Job 关注的是数据,增长了弹性扩容和数据分片的思路,以便于更大限度的利用分布式服务器的资源,可是学习成本相对高些,推荐在“数据量庞大,且部署服务器数量较多”时使用算法
  • X-Job采用了中心化思想的架构,而E-Job采用了无中心的架构
功能特性
简单灵活
  • 提供Web页面对任务进行管理,管理系统支持用户管理、权限控制;
  • 支持容器部署;
  • 支持通过通用HTTP提供跨平台任务调度;
丰富的任务管理功能
  • 支持页面对任务CRUD操作;
  • 支持在页面编写脚本任务、命令行任务、Java代码任务并执行;
  • 支持任务级联编排,父任务执行结束后触发子任务执行;
  • 支持设置任务优先级;
  • 支持设置指定任务执行节点路由策略,包括轮询、随机、广播、故障转移、忙碌转移等;
  • 支持Cron方式、任务依赖、调度中心API接口方式触发任务执行
高性能
  • 调度中心基于线程池多线程触发调度任务,快任务、慢任务基于线程池隔离调度,提供系统性能和稳定性;
  • 任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰;
高可用
  • 任务调度中心、任务执行节点均 集群部署,支持动态扩展、故障转移
  • 支持任务配置路由故障转移策略,执行器节点不可用是自动转移到其他节点执行
  • 支持任务超时控制、失败重试配置
  • 支持任务处理阻塞策略:调度当任务执行节点忙碌时来不及执行任务的处理策略,包括:串行、抛弃、覆盖策略
易于监控运维
  • 支持设置任务失败邮件告警,预留接口支持短信、钉钉告警;
  • 支持实时查看任务执行运行数据统计图表、任务进度监控数据、任务完整执行日志;
整体架构设计

将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求;

将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑,因此,“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性;

调度模块(调度中心)

负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码

调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块; 支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover

功能
  1. 任务管理:对调度的任务进行触发时间等配置
  2. 日志管理:查看调度的日志情况
  3. 执行器管理:管理接入的业务模块
  4. 其它,比如用户权限配置和运行统计报表等功能
执行模块(执行器)

负责接收调度请求并执行任务逻辑。

任务模块专注于任务的执行等操作,开发和维护更加简单和高效; 接收“调度中心”的执行请求、终止请求和日志请求等

工作原理
  • 任务执行器根据配置的调度中心的地址,自动注册到调度中心
  • 达到任务触发条件,调度中心下发任务
  • 执行器基于线程池执行任务,并把执行结果放入内存队列中、把执行日志写入日志文件中
  • 执行器的回调线程消费内存队列中的执行结果,主动上报给调度中心
  • 当用户在调度中心查看任务日志,调度中心请求任务执行器,任务执行器读取任务日志文件并返回日志详情

 

部署调度中心
初始化数据库

https://gitee.com/xuxueli0323/xxl-job地址下载项目源码并解压, SQL脚本位置在

/xxl-job/doc/db/tables_xxl_job.sql

 

创建用户并授权
mysql> source /opt/tables_xxl_job.sql;
mysql> CREATE USER 'xxl'@'%' IDENTIFIED BY 'xxl';
mysql> GRANT ALL ON xxl_job.* TO 'xxl'@'%' IDENTIFIED BY 'xxl' WITH GRANT OPTION;
源码结构
解压源码,按照maven格式将源码导入IDE, 使用maven进行编译即可

xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
    :xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;
    :xxl-job-executor-sample-frameless:无框架版本;
配置调度中心
调度中心项目是xxl-job-admin,作用是统计管理调度平台上面的任务,负责触发以及执行调度任务,并且提供任务管理

修改application.properties
调度中心配置内容说明,可以按需进行修改

server.port=8080
#项目访问路径
server.servlet.context-path=/xxl-job-admin
spring.datasource.url=jdbc:mysql://192.168.10.30:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=xxl
spring.datasource.password=xxl
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### 报警邮箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
### 调度中心通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 调度中心国际化配置 [必填]: 默认为 "zh_CN"/中文简体, 可选范围为 "zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文;
xxl.job.i18n=zh_CN
## 调度线程池最大线程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100
### 调度中心日志表数据保存天数 [必填]:过期日志自动清理;限制大于等于7时生效,否则, 如-1,关闭自动清理功能;
xxl.job.logretentiondays=30


部署项目

可以在本地直接运行xxl-job服务,或者打包后在服务器上面运行

启动服务

运行项目后访问 http://192.168.10.30:8080/xxl-job-admin ,该地址执行器将会使用到,作为回调地,默认登录账号 admin/123456, 登录后运行界面如下图所示

 

Docker部署
创建docker-comopose.yml
version: '3'
services:
  xxl-job-admin:
    image: xuxueli/xxl-job-admin:2.3.0
    restart: always
    container_name: xxl-job-admin
    environment:
      PARAMS: '--spring.datasource.url=jdbc:mysql://192.168.10.30:3306/xxl_job?Unicode=true&characterEncoding=UTF-8 --spring.datasource.username=root --spring.datasource.password=root'
    ports:
      - 8080:8080
    volumes:
      - ./data/applogs:/data/applogs
启动服务
docker-compose up -d
部署执行器
引入依赖
在项目pom文件中引入了 “xxl-job-core” 的maven依赖;

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.3.0</version>
</dependency>
执行器配置文件
如调度中心集群部署存在多个地址则用逗号分隔

### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://192.168.10.30:8080/xxl-job-admin
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-task
### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
xxl.job.executor.address=
### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=
### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9999
### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
xxl.job.executor.logretentiondays=30
配置执行器
@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${xxl.job.accessToken}")
    private String accessToken;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Value("${xxl.job.executor.address}")
    private String address;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private int port;

    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;


    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }
}
启动执行器

本地执行器服务启动后,需要在调度中心配置执行器

注意AppName就是执行器项目配置的配置项,名称可以随意,机器地址采用自动注册就可以

 

作业详情

xxl-job支持很多种任务模式,下面我们挑几个常用的介绍下

BEAN模式

Bean模式任务,支持基于方法的开发方式,每个任务对应一个方法。

原理

每个Bean模式任务都是一个Spring的Bean类实例,它被维护在“执行器”项目的Spring容器中。

任务类需要加“@JobHandler(value=”名称”)”注解,因为“执行器”会根据该注解识别Spring容器中的任务。任务类需要继承统一接口“IJobHandler”,任务逻辑在execute方法中开发,因为“执行器”在接收到调度中心的调度请求时,将会调用“IJobHandler”的execute方法,执行任务逻辑。

编写执行器

为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。

@Component
public class XxlJobBeanMethodTask {

    private static final Logger logger = LoggerFactory.getLogger(XxlJobBeanMethodTask.class);

    @XxlJob("methodTask")
    public void methodTask() throws Exception {
        logger.info("methodTask定时任务启动,总分片:{},当前分片:{},参数:{}",XxlJobHelper.getShardIndex(),XxlJobHelper.getShardIndex(),XxlJobHelper.getJobParam());
        XxlJobHelper.log("XXL-METHODTASK, methodTask定时任务启动");
        //执行成功标志,默认就是执行成功
        XxlJobHelper.handleSuccess();
    }
}
新建调度任务

在任务管理,选择对应的执行器新建任务

 新增完成后,可以在列表点击执行一次或者点击启动启动定时任务

GLUE模式(Java)

任务以源代码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler

原理

每个 “GLUE模式(Java)” 任务的代码,实际上是“一个继承自“IJobHandler”的实现类的类代码”,“执行器”接收到“调度中心”的调度请求时,会通过Groovy类加载器加载此代码,实例化成Java对象,同时注入此代码中声明的Spring服务(请确保Glue代码中的服务和类引用在“执行器”项目中存在),然后调用该对象的execute方法,执行任务逻辑。

新建调度任务

新建一个任务,注意使用使用GLUE(JAVA)模式

 

在线编辑代码

添加任务后,选择刚刚添加的GLUE(JAVA)任务,选中指定任务后,点击该任务右侧“GLUE IDE”按钮,将会前往GLUE任务的Web IDE界面

 

在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)

路由策略

路由策略属于XXLJob的高级功能,可以控制执行器执行的策略

 

准备工作

启动多台XXL执行器的服务,我们启动三台服务,并查看控制台的注册情况

 

第一个

当选择该策略时,会选择执行器注册地址的第一台机器执行,如果第一台机器出现故障,则调度任务失败

查看客户端日志

我们查看客户端日志,发现服务器已经调度了第一个节点

 

 

关闭客户端

我们通过执行器的注册节点发现,第一台服务器的执行器是8089端口的服务器,我们将8089服务器给关闭,然后查看执行器日志,我们发现服务执行失败

 

容错策略

但是并不会一直报错,等一段时间控制台会将已经挂掉的节点剔除出去,第一个节点已经变成了8189就可以继续执行了

 

最后一个

当选择该策略时,会选择执行器注册地址的最后一台机器执行,如果最后一台机器出现故障,则调度任务失败,测试方式如上

轮询

当选择该策略时,会按照执行器注册地址轮询分配任务,如果其中一台机器出现故障,调度任务失败,任务不会转移

随机

当选择该策略时,会按照执行器注册地址随机分配任务,如果其中一台机器出现故障,调度任务失败,任务不会转移

一致性HASH

当选择该策略时,每个任务按照Hash算法固定选择某一台机器,如果那台机器出现故障,调度任务失败,任务不会转移。

最不经常使用

当选择该策略时,会优先选择使用频率最低的那台机器,如果其中一台机器出现故障,调度任务失败,任务不会转移(实践表明效果和轮询策略一致)

最近最久未使用

当选择该策略时,会优先选择最久未使用的机器,如果其中一台机器出现故障,调度任务失败,任务不会转移(实践表明效果和轮询策略一致)

故障转移

当选择该策略时,按照顺序依次进行心跳检测,如果其中一台机器出现故障,则会转移到下一个执行器,若心跳检测成功,会选定为目标执行器并发起调度

忙碌转移

当选择该策略时,按照顺序依次进行空闲检测,如果其中一台机器出现故障,则会转移到下一个执行器,若空闲检测成功,会选定为目标执行器并发起调度

分片广播

当选择该策略时,广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数,可根据分片参数开发分片任务,如果其中一台机器出现故障,则该执行器执行失败,不会影响其他执行器

XXL的分片是根据启动的客户端进行分片,

分片参数是调度中心自动传递的,不用我们手动传递,且集群中的每个index序号是固定的,即使集群中有项目宕机,也不影响其他项目的index序号,当重启宕机项目时,它的序号还是原先的

服务启动后会自动的进行服务分片,分片会根据不同的节点进行调度

阻塞策略

调度过于密集执行器来不及处理时的处理策略

准备工作

修改代码加入延时操作模拟定时任务执行超时

 

@Component
public class XxlJobBeanMethodTask {

    private static final Logger logger = LoggerFactory.getLogger(XxlJobBeanMethodTask.class);

    @XxlJob("methodTask")
    public void methodTask() throws Exception {
        logger.info("methodTask定时任务启动,总分片:{},当前分片:{},参数:{}",XxlJobHelper.getShardTotal(),XxlJobHelper.getShardIndex(),XxlJobHelper.getJobParam());
        XxlJobHelper.log("XXL-METHODTASK, methodTask定时任务启动");
        //休眠10S模拟服务执行超时
        Thread.sleep(10000);
        //执行成功标志,默认就是执行成功
        XxlJobHelper.handleSuccess();
    }
}
单机串行

调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行

测试

将阻塞策略设置为单机串行,当执行的任务耗时过长,同一个任务将进入执行队列等待执行,这个时候将任务停止掉,执行器还会将队列中的任务执行完成

 但是执行器还在继续执行队列中的任务,直到所有任务执行完成

 

等一段时间后,我们发现定时任务状态都已经正常了

 

丢弃后续调度

调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败

测试

将阻塞策略设置为丢弃后续调度,执行器发现调度未完成则直接设置为失败

 

覆盖之前调度

调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务

测试

将阻塞策略设置为覆盖之前调度,执行器发现有任务正在调度直接将该任务设置为失败,任何进行后续调度任务

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

吴恩达深度学习笔记:深度学习的 实践层面 (Practical aspects of Deep Learning)1.6-1.8

目录 第一门课&#xff1a;第二门课 改善深层神经网络&#xff1a;超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第一周&#xff1a;深度学习的 实践层面 (Practical aspects of Deep Learning)…

某赛通电子文档安全管理系统 多处 SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

【智能算法】向日葵优化算法(SFO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2019年&#xff0c;GF Gomes等人受到自然界向日葵运动行为启发&#xff0c;提出了向日葵优化算法&#xff08;Sunflower Optimization, SFO&#xff09;。 2.算法原理 2.1算法思想 SFO模拟向日葵行…

Android某钉数据库的解密分析

声明 1 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 目的 1 解密app数据库&#xff0c;用数据库软件打开查看信息内容 入手…

C语言数据类型的介绍,类型的基本归类,整型在内存中的存储,原码、反码、补码,大小端等介绍

文章目录 前言一、数据类型的介绍类型的意义 1. 类型的基本归类&#xff08;1&#xff09;. 整型家族&#xff08;2&#xff09;. 浮点数家族&#xff08;3&#xff09;. 构造类型&#xff08;4&#xff09;. 指针类型&#xff08;5&#xff09;. 空类型 二、整型在内存中的存储…

【网络安全】安全事件管理处置 — 安全事件处置思路指导

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 一、处理DDOS事件 1.准备工作 2.预防工作 3.检测与分析 4.限制、消除 5.证据收集 二、处理恶意代码事件 1.准备 2.预防 3.检测与分析 4.限制 5.证据收集 6.消除与恢复 …

NodeJS基础知识

文章目录 **1. Node.js平台与架构****1.1 Node.js简介****1.2 事件循环&#xff08;Event Loop&#xff09;** **2. JavaScript基础知识****2.1 ECMAScript版本****2.2 变量、数据类型、运算符****2.3 函数****2.4 类与面向对象编程** **3. Node.js核心API****3.1 全局对象与内…

Linux下载及安装OpenSSL

文章目录 前言一、OpenSSL下载二、OpenSSL安装1.上传下载好的安装包到服务器2.解压3.切换目录4.配置config5.编译6.安装7.备份旧版本OpenSSL7.创建软链接8.添加OpenSSL动态链接库9.更新库缓存10.查看OpenSSL版本验证安装是否成功 前言 一般系统会自带有OpenSSL&#xff0c;我们…

OpenHarmony实战开发-媒体查询 (@ohos.mediaquery)

概述 媒体查询作为响应式设计的核心&#xff0c;在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式。媒体查询常用于下面两种场景&#xff1a; 针对设备和应用的属性信息&#xff08;比如显示区域、深浅色、分辨率&#xff09;&#xff0…

大数据第五天(操作hive的方式)

文章目录 操作hive的方式hive 存储位置hive 操作语法创建数据表的方式 操作hive的方式 hive 存储位置 hive 操作语法 创建数据表的方式 – 创建数据库 create database if not exists test我们创建数据库表的时候&#xff0c;hive是将我们的数据自动添加到数据表中&#xf…

Matlab|交直流系统潮流计算(含5种控制模式)

目录 1 主要内容 程序参考流程图 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序参考文献《交直流系统潮流计算及相互关联特性分析》&#xff0c;采用5种交直流潮流控制方式&#xff1a;1.定电流定电压 2.定电流定熄弧角 3.定功率定电压 4.定功率定熄弧角 5.定触发角…

C++进阶:多态

目录 一、多态的概念 二、多态的实现 1.多态的实现条件 2.虚函数 3.虚函数的重写(覆盖) 三、概念比较 四、抽象类 1.概念 2.接口继承与实现继承 一、多态的概念 在生活中我们通常会遇到以下的一个场景&#xff1a;领支付宝的红包。 明明都是同一个红包&#xff0c;不同…

Qt配置CMake出错

一个项目需要在mingw环境下编译Opencv源码&#xff0c;当我用Qt配置opencv的CMakeLists.txt时&#xff0c;出现了以下配置错误&#xff1a; 首先我根据下述博文介绍&#xff0c;手动配置了CMake&#xff0c;但仍不能解决问题。 Qt(MinGW版本)安装 - 夕西行 - 博客园 (cnblogs.…

鸿蒙(HarmonyOS)性能优化实战-Trace使用教程

概述 OpenHarmony的DFX子系统提供了为应用框架以及系统底座核心模块的性能打点能力&#xff0c;每一处打点即是一个Trace&#xff0c;其上附带了记录执行时间、运行时格式化数据、进程或线程信息等。开发者可以使用SmartPerf-Host调试工具对Trace进行解析&#xff0c;在其绘制…

人工智能如何提高公司效率的 5 种方法

人工智能是当今最热门的话题之一&#xff0c;但并不是每个人都了解其对商业的价值规模。由此可见&#xff0c;现有的AI技术可以将企业的生产力提升40%。 在机器学习的帮助下&#xff0c;Netflix 利用自动化个性化推荐每年赚取 10 亿美元。当公司使用人工智能时&#xff0c;34%…

线性代数:抽象向量空间

一、说明 有些函数系列极具线性代数的向量特征。这里谈及多项式构成函数的线性代数意义。问题是这个主题能展开多少内涵&#xff1f;请看本文的论述。 二、线性空间和向量 让我先问你一个简单的问题。什么是向量&#xff1f;为了方便起见&#xff0c;二维箭头从根本上说是平…

Web前端一套全部清晰 ③ day2 HTML 标签综合案例

别让平淡生活&#xff0c;耗尽所有向往 —— 24.4.26 综合案例 —— 一切都会好的 网页制作思路&#xff1a;从上到下&#xff0c;先整体到局部&#xff0c;逐步分析制作 分析内容 ——> 写代码 ——>保存——>刷新浏览器&#xff0c;看效果 <!DOCTYPE html> &l…

IDEA生成测试类

方法一 具体流程: 选中要生成的测试类------------>选择code选项------------>选择Generate选项---------->选择test选项---------->选择要生成的方法 第一步: 光标选中需要生成测试类的类 找到code选项 选中Generate选项 选中test选项 选中你要生成的测试…

【智能算法】囊状虫群算法(TSA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2020年&#xff0c;S Kaur等人受到囊状虫群自然行为启发&#xff0c;提出了囊状虫群算法&#xff08;Tunicate Swarm Algorithm, TSA&#xff09;。 2.算法原理 2.1算法思想 TSA模拟了囊状虫群在导…

Scala的函数至简原则

对于scala语言来说&#xff0c;函数的至简原则是它的一大特色。下面让我们一起来看看分别有什么吧&#xff01; 函数至简原则&#xff1a;能省则省&#xff01; 初始函数 def test(name:String):String{return name }1、return可以省略&#xff0c;Scala会使用函数体的最后一…
最新文章