当前位置: 首页 > news >正文

JavaEE之定时器及自我实现

在生活当中,有很多事情,我们不是立马就去做,而是在规定了时间之后,在到该时间时,再去执行,比如:闹钟、定时关机等等,在程序的世界中,有些代码也不是立刻执行,那么我们该如何实现呢?一探究竟——>《定时器》

1. 定时器

定时器是什么

定时器也是软件开发中的⼀个重要组件.类似于⼀个"闹钟".达到⼀个设定的时间之后,就执行某个指定好的代码.
定时器是⼀种实际开发中非常常用的组件.
比如网络通信中,如果对方500ms内没有返回数据,则断开连接尝试重连.
比如⼀个Map,希望里面的某个key在3s之后过期(自动删除).
类似于这样的场景就需要用到定时器.

在Java当中也给我们提供了定时器(Timer)的类,请见下文。

标准库中的定时器

  • 标准库中提供了一个Timer类.Timer类的核心方法为schedule
  • schedule 包含两个参数.第⼀个参数指定即将要执行的任务代码,第⼆个参数指定多长时间之后执行(单位为毫秒).

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 自我实现一个定时器

1.首先定时器是用于处理任务的,我们该如何在定时器当中管理任务呢??

我们通过一个类,描述任务和任务执行的时间
具体任务的逻辑用Runnble表示,执行时间的可以用一个long型delay去表示

/*** 任务类*///由于需要比较时间大小,所以使用接口
class MyTask implements Comparable<MyTask>{//任务private Runnable runnable = null;//延迟时间private long time = 0;public MyTask(Runnable runnable, long delay) {//任务不能为空if(runnable==null){throw new RuntimeException("任务不能为空...");}//时间不能为负数if(delay<0){throw new RuntimeException("时间不能为负数...");}this.runnable = runnable;// 计算出任务执行的具体时间this.time = delay+System.currentTimeMillis();}public Runnable getRunnable() {return runnable;}public long getTime() {return time;}//比较当前任务和其他任务的时间@Overridepublic int compareTo(MyTask o) {return (int) (o.getTime()-this.getTime());}
}

2.通过MyTask描述了任务之后,由于任务的执行顺序不一样,我们该如何去管理任务呢?

我们通过一个优先级队列把任务的对象组织起来

//用阻塞队列来管理任务
private BlockingQueue<MyTask> queue=new PriorityBlockingQueue<>();

3.我们描述完了任务也通过优先级队列管理了任务对象,我们如何让任务对象和定时器关联起来呢?

    /*** 添加任务的方法* @param runnable 任务* @param delay 延时* @throws InterruptedException*/public void schedule(Runnable runnable, long delay) throws InterruptedException {// 根据传处的参数,构造一个MyTaskMyTask task=new MyTask(runnable,delay);// 把任务放入阻塞队列queue.put(task);}
}

4.我们通过schedule方法把任务对象添加到了阻塞队列当中,我们只需要创建一个线程来执行任务即可

此时我们的思路是:创建一个线程不停的扫描任务,取出队列的首元素若时间到就取出执行,时间没到就放回队列不执行,就能写出以下代码:

    // 创建扫描线程Thread thread=new Thread(()->{//不断的扫描队列中的任务while (true){try {//1.从阻塞队列中获取任务MyTask task = queue.take();//2.判断到没到执行时间long currentTime=System.currentTimeMillis();if(currentTime>=task.getTime()){//时间到了就执行任务task.getRunnable().run();}else {// 没有到时间,重新放回队列queue.put(task);}}catch (InterruptedException e) {e.printStackTrace();}}},"scanThread");//启动线程thread.start();      

但是上面的代码有一个很明显的问题,就是 “忙等” ,为什么呢?
在这里插入图片描述
那么我们怎么解决这个忙等这个问题呢?

在放回队列时让程序等待一段时间等待一段时间
时间为:下一个任务的执行时间和当前时间的差
那么既然要等待了我们必须要通过持有同一个锁,来完成等待操作,所以我们创建一把锁

修改代码如下:

// 创建扫描线程
Thread thread=new Thread(()->{//不断的扫描队列中的任务while (true){try {//1.从阻塞队列中获取任务MyTask task = queue.take();//2.判断到没到执行任务的时间long currentTime=System.currentTimeMillis();if(currentTime>=task.getTime()){//时间到了就执行任务task.getRunnable().run();}else {// 当前时间与任务执行时间的差long waitTime = task.getTime() - currentTime;// 没有到时间,重新放回队列queue.put(task);synchronized (locker){//等时间locker.wait(waitTime);}}}catch (InterruptedException e) {e.printStackTrace();}}},"scanThread");//启动线程,真正去系统中申请资源thread.start();

通过锁,解决了忙等问题,

5.此时还有一个新的问题,在该队列中若产生了新的任务执行时间在等待任务之前该怎么办呢?

我们在每一次向阻塞队列当中添加新任务时,我们就唤醒一次扫描线程即可

/*** 添加任务的方法* @param runnable 任务* @param delay 延时* @throws InterruptedException*/public void schedule(Runnable runnable, long delay) throws InterruptedException {// 根据传处的参数,构造一个MyTaskMyTask task=new MyTask(runnable,delay);// 把任务放入阻塞队列queue.put(task);//在每次添加新任务时,唤醒一次扫描线程,以访扫描线程还在等待,新任务时间过了的问题synchronized (locker){locker.notifyAll();}}
}

6.CPU调度的过程中可能会产生执行顺序的问题,或当一个线程执行到一半的时间被调度走的现象,会引发什么问题呢?

在这里插入图片描述

造成该现象的原因是没有保证原子性,我们扩大锁范围即可解决该问题,修改后的代码如下:

//不断的扫描队列中的任务while (true){synchronized (locker){try {//1.从阻塞队列中获取任务MyTask task = queue.take();//2.判断到没到执行任务的时间long currentTime=System.currentTimeMillis();if(currentTime>=task.getTime()){//时间到了就执行任务task.getRunnable().run();}else {// 当前时间与任务执行时间的差long waitTime = task.getTime() - currentTime;// 没有到时间,重新放回队列queue.put(task);locker.wait(waitTime);}}catch (InterruptedException e) {e.printStackTrace();}}}

7.由于进入锁之后,MyTask task = queue.take();操作,当阻塞队列中没有元素时,就会阻塞等待,直到队列中有可用元素才继续执行,但是由于MyTask task = queue.take();操作持有了锁,导致无法释放锁,添加任务的方法又迟迟取不到锁,导致一个在等着任务执行,一个在等着获取锁添加任务,造成了“死锁”现象,我们该如何解决呢?

我们发现在为了解决原子性问题时,我们扩大加锁的范围,却又引入了更大的问题
一般我们两害相全取其轻

为了解决无法及时执行任务的问题,我们创建了一个后台的扫描线程,只做定时唤醒操作,定时1s或者任意时间唤醒执行一次


完整的定时器实现代码如下:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;/*** 自我实现定时器*/
public class MyTimer {//用阻塞队列来管理任务private BlockingQueue<MyTask> queue=new PriorityBlockingQueue<>();//创建⼀个锁对象private Object locker = new Object();public MyTimer() throws InterruptedException {// 创建扫描线程Thread thread=new Thread(()->{//不断的扫描队列中的任务while (true){synchronized (locker){try {//1.从阻塞队列中获取任务MyTask task = queue.take();//2.判断到没到执行任务的时间long currentTime=System.currentTimeMillis();if(currentTime>=task.getTime()){//时间到了就执行任务task.getRunnable().run();}else {// 当前时间与任务执行时间的差long waitTime = task.getTime() - currentTime;// 没有到时间,重新放回队列queue.put(task);locker.wait(waitTime);}}catch (InterruptedException e) {e.printStackTrace();}}}},"scanThread");//启动线程,真正去系统中申请资源thread.start();//创建一个后台线程Thread daemonThread= new Thread(()->{while (true){//定时唤醒synchronized (locker){locker.notifyAll();}//休眠一会try {TimeUnit.MICROSECONDS.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}});//设置成后台线程daemonThread.setDaemon(true);//启动线程daemonThread.start();}/*** 添加任务的方法* @param runnable 任务* @param delay 延时* @throws InterruptedException*/public void schedule(Runnable runnable, long delay) throws InterruptedException {// 根据传处的参数,构造一个MyTaskMyTask task=new MyTask(runnable,delay);// 把任务放入阻塞队列queue.put(task);synchronized (locker){locker.notifyAll();}}
}/*** 任务类*/
class MyTask implements Comparable<MyTask>{//任务private Runnable runnable = null;//延迟时间private long time = 0;public MyTask(Runnable runnable, long delay) {//任务不能为空if(runnable==null){throw new RuntimeException("任务不能为空...");}//时间不能为负数if(delay<0){throw new RuntimeException("时间不能为负数...");}this.runnable = runnable;// 计算出任务执行的具体时间this.time = delay+System.currentTimeMillis();}public Runnable getRunnable() {return runnable;}public long getTime() {return time;}@Overridepublic int compareTo(MyTask o) {return (int) (o.getTime()-this.getTime());}
}

相关文章:

JavaEE之定时器及自我实现

在生活当中&#xff0c;有很多事情&#xff0c;我们不是立马就去做&#xff0c;而是在规定了时间之后&#xff0c;在到该时间时&#xff0c;再去执行&#xff0c;比如&#xff1a;闹钟、定时关机等等&#xff0c;在程序的世界中&#xff0c;有些代码也不是立刻执行&#xff0c;…...

好用的php商城源码有哪些?

选择一个优秀的商城工具&#xff0c;能更好地帮助大家建立一个好用的商城系统。目前比较流行的都是开源PHP商城系统&#xff0c;那么现实中都有哪些好用的PHP商城源码值得推荐呢&#xff1f;下面就带大家一起来了解一下。 1.TigShop 【推荐指数】&#xff1a;★★★★★☆ 【推…...

GO语言实现KMP算法

前言 本文结合朱战立教授编著的《数据结构—使用c语言&#xff08;第五版&#xff09;》&#xff08;以下简称为《数据结构&#xff08;第五版&#xff09;朱站立》&#xff09;中4.4.2章节内容编写&#xff0c;KMP的相关概念可参考此书4.4.2章节内容。原文中代码是C语言&…...

国产Docker可视化面板Dpanel的安装与功能解析

国产Docker可视化面板Dpanel的安装及功能介绍 Docker 可视化面板系统&#xff0c;提供完善的 docker 管理功能。 支持查看基本信息、运行状态统计、网络统计、磁盘统计、用量统计等功能 ​​ ​​ 容器管理&#xff1a; ​​ 创建/修改容器 ​​ 支持基本配置、环境变量、…...

Elaticsearch常用的浏览器插件

Elasticsearch head https://github.com/mobz/elasticsearch-headElasticsearch Tools https://www.chajianxw.com/developer/31765.html#google_vignetteElasticvue https://blog.csdn.net/weixin_60457220/article/details/143595846...

LabVIEW数据库管理系统

LabVIEW数据库管理系统&#xff08;DBMS&#xff09;是一种集成了数据库技术与数据采集、控制系统的解决方案。通过LabVIEW的强大图形化编程环境&#xff0c;结合数据库的高效数据存储与管理能力&#xff0c;开发人员可以实现高效的数据交互、存储、查询、更新和报告生成。LabV…...

【HM-React】08. Layout模块

基本结构和样式reset 结构创建 实现步骤 打开 antd/Layout 布局组件文档&#xff0c;找到示例&#xff1a;顶部-侧边布局-通栏拷贝示例代码到我们的 Layout 页面中分析并调整页面布局 代码实现 pages/Layout/index.js import { Layout, Menu, Popconfirm } from antd impor…...

SpringCloud

1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#xff1a;将业务的所有功…...

HarmonyOS应用开发者初级认证最新版– 2025/1/13号题库新版

1.欢迎各位读者&#xff0c;本文档来自鸿蒙开发学员亲测&#xff0c;最新版。&#xff08;考试时直接Ctrlf进行搜索&#xff0c;一定要认真比对答案&#xff0c;有的答案相似度很高&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 欢迎…...

基于微信小程序的汽车销售系统的设计与实现springboot+论文源码调试讲解

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…...

[免费]SpringBoot+Vue新能源汽车充电桩管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue新能源汽车充电桩管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue新能源汽车充电桩管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 随着信息化时代的到来&#xff0…...

《机器学习》之K-means聚类

目录 一、简介 二、K-means聚类实现步骤 1、初始化数据点、确定K值 2、通过距离分配数据点 3、更新簇中心 4、 迭代更新 三、聚类效果评价方式 1、轮廓系数的定义 2、整体轮廓系数 3、使用场景 4、优点 5、缺点 6、代码实现方法 四、K-means聚类代码实现 1、API接…...

【芯片封测学习专栏 -- 2D | 2.5D | 3D 封装的区别和联系】

请阅读【嵌入式开发学习必备专栏 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目录 Overview线键合&#xff08;wire-bonding&#xff09;封装FOWLP2D封装2.5D 封装硅通孔(TSV)硅中介层无TSV的2.5D 3D封装 Overview 我们先要了解一下&…...

E12.【C语言】练习:求两个数的最大公约数

目录 1.枚举 2.辗转相除法 1.枚举 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() {int a 0;int b 0;int tmp 0;scanf("%d %d", &a, &b);if (a < b){for (int i1; i < a; i){if (0a% i && 0b%i)tmp i;}}if …...

SVG图表

1、时序图 英文 #mermaid-svg-OyLuBTPnpbW9XDOB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-OyLuBTPnpbW9XDOB .error-icon{fill:#552222;}#mermaid-svg-OyLuBTPnpbW9XDOB .error-text{fill:#552222;stroke:#55…...

IDEA中创建maven项目

1. IDEA中创建maven项目 在IDEA中创建Maven项目&#xff0c;前提是已经安装配置好Maven环境。如还未配置安装Maven的&#xff0c;请先下载安装。如何下载安装&#xff0c;可参考我另外篇文章&#xff1a;maven的下载与安装教程本篇教程是以创建基于servlet的JavaWeb项目为例子&…...

Laravel 中 Cache::remember 的基本用途

在 Laravel 中&#xff0c;Cache::remember 方法用于缓存数据&#xff0c;以提高应用程序的性能。当需要从数据库或其他较慢的数据源中检索数据时&#xff0c;可以使用 Cache::remember 来检查请求的数据是否已经被缓存。如果数据已缓存&#xff0c;则直接从缓存中读取&#xf…...

云数赋能:开启企业数字化转型的高速通道

目录 一、引言&#xff1a;数字化转型浪潮下的企业挑战与机遇 二、认识云数赋能 2.1 云计算&#xff1a;企业数字化的强大基石 2.2 大数据&#xff1a;挖掘企业潜藏价值的宝藏 三、云数赋能如何加速企业数字化转型 3.1 优化企业运营管理 3.2 提升客户体验 3.3 推动创新…...

Spring底层核心原理解析

​ 本次分享会把Spring中核心知识点都给大家进行串讲&#xff0c;让大家对Spring的底层有一个整体的大致了解&#xff0c;比如&#xff1a; Bean的生命周期底层原理依赖注入底层原理初始化底层原理推断构造方法底层原理AOP底层原理Spring事务底层原理 但都只是大致流程&#…...

昵称 校验

1. 基本格式校验 1. 长度限制 • 设置最小和最大字符长度&#xff1a;2-20 个字符&#xff08;常见范围&#xff09;。 • 避免昵称过短或过长影响显示和识别。 • 示例&#xff1a; • 2 ≤ 长度 ≤ 20&#xff1a;let minLength 2 let maxLength 20 if nickname.count <…...

25/1/12 嵌入式笔记 学习esp32

了解了一下位选线和段选线的知识&#xff1a; 位选线&#xff1a; 作用&#xff1a;用于选择数码管的某一位&#xff0c;例如4位数码管的第1位&#xff0c;第2位&#xff09; 通过控制位选线的电平&#xff08;高低电平&#xff09;&#xff0c;决定当前哪一位数码管处于激活状…...

PostgreSQL 超级管理员详解

1. 什么是 PostgreSQL 超级管理员 PostgreSQL 超级管理员&#xff08;superuser&#xff09;是拥有数据库系统最高权限的用户。他们可以执行任何数据库操作&#xff0c;包括但不限于创建和删除数据库、用户、表空间、模式等。超级管理员权限是 PostgreSQL 中权限的最高级别。 …...

【centos】校时服务创建-频率修改

在 NTP 配置中&#xff0c;校时频率通常是由 NTP 协议自动管理的&#xff0c;NTP 会根据网络延迟和时间偏差动态调整校时频率。不过&#xff0c;您可以通过配置文件中的一些参数来影响 NTP 的行为。 如果想要更改 NTP 的校时频率&#xff0c;可以考虑以下几个方面&#xff1a;…...

mybatis分页插件:PageHelper、mybatis-plus-jsqlparser(解决SQL_SERVER2005连接分页查询OFFSET问题)

文章目录 引言I PageHelper坐标II mybatis-plus-jsqlparser坐标Spring Boot 添加分页插件自定义 Mapper 方法中使用分页注意事项解决SQL_SERVER2005连接分页查询OFFSET问题知识扩展MyBatis-Plus 框架结构mybatis-plus-jsqlparser的 Page 类引言 PageHelper import com.github.p…...

二、模型训练与优化(4):模型优化-实操

下面我将以 MNIST 手写数字识别模型为例&#xff0c;从 剪枝 (Pruning) 和 量化 (Quantization) 两个常用方法出发&#xff0c;提供一套可实际动手操作的模型优化流程。此示例基于 TensorFlow/Keras 环境&#xff0c;示范如何先训练一个基础模型&#xff0c;然后对其进行剪枝和…...

开发人员学习书籍推荐(C#、Python方向)

作为一名开发人员&#xff0c;持续学习和提升自己的技术水平是至关重要的。如今&#xff0c;技术不断更新换代&#xff0c;新的开发框架、语言和工具层出不穷。对于刚入行的开发者或希望深入某一领域的工程师来说&#xff0c;选对书籍是学习的捷径之一。本篇文章将推荐一些经典…...

【HTML+CSS+JS+VUE】web前端教程-31-css3新特性

圆角 div{width: 100px;height: 100px;background-color: saddlebrown;border-radius: 5px;}阴影 div{width: 200px;height: 100px;background-color: saddlebrown;margin: 0 auto;box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5);}...

【Elasticsearch】批量操作:优化性能

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探…...

sklearn-逻辑回归-制作评分卡

目录 数据集处理 分箱 分多少个箱子合适 分箱要达成什么样的效果 对一个特征进行分箱的步骤 分箱的实现 封装计算 WOE 值和 IV值函数 画IV曲线&#xff0c;判断最佳分箱数量 结论 pd.qcut 执行报错 功能函数封装 判断分箱个数 在银行借贷场景中&#xff0c;评分卡是…...

Saas数据库迁移单租户数据

1、背景 租户使用Saas系统&#xff0c;用一段时间后要将系统、数据搬迁到自建服务器。该Saas系统没有按租户分库&#xff0c;且数据库数据量太大&#xff0c;需要将单租户的数据抽取出来。Saas系统使用Mysql5.7数据库&#xff0c;主要使用INFORMATION_SCHEMA.COLUMNS表进行数据…...

23_Spring Boot中Redis缓存实现

1.基于注解的Redis缓存实现 下面我们在之前Spring Boot默认缓存管理的基础上引入Redis缓存组件,使用基于注解的方式讲解Spring Boot整合Redis缓存的具体实现。 1.使用@Cacheable、@CachePut、@CacheEvict注解定制缓存管理。对CommentServiceImpl类中的方法进行修改,使用@Ca…...

Vue 学习之旅:核心技术学习总结与实战案例分享(vue指令下+计算属性+侦听器)

Vue 学习之旅&#xff1a;核心技术学习总结与实战案例分享 文章目录 Vue 学习之旅&#xff1a;核心技术学习总结与实战案例分享一、指令补充&#xff08;一&#xff09;指令修饰符&#xff08;二&#xff09;v-bind 对样式操作的增强&#xff08;三&#xff09;v-model 应用于其…...

【Linux网络编程】数据链路层 | MAC帧 | ARP协议

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 &#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系…...

vscode vue 自动格式化

vscode vue 自动格式化 安装Prettier和Vetur插件 选择设置&#xff0c;并且转到编辑文件。增加如下内容。 {"editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","[vue]": {"editor.defaultFor…...

GitCode G-Star 光引计划终审前十名获奖项目公示

在技术的浩瀚星空中&#xff0c;GitCode 平台上的 G-Star 项目熠熠生辉。如今&#xff0c;“光引计划” 已圆满落幕&#xff0c;众多 G-Star 项目作者&#xff0c;一同分享项目在 GitCode 平台托管的宝贵体验&#xff0c;并深入挖掘平台的多样玩法。 众多投稿纷至沓来&#xf…...

Postgres14.4(Docker安装)

Postgres14.4&#xff08;Docker安装&#xff09; 一&#xff0c;Docker拉取镜像 docker pull postgres:14.4 #检查镜像是否拉取成功 docker images | grep postgres二&#xff0c;新建挂载目录&#xff0c;并运行容器 mkdir -p /data/postgre/data chmod 777 /data/postgre/…...

R.swift库的详细用法

R.swift 是一个 Swift 工具库,它提供了一个自动生成的类 R,使得你可以通过类型安全的方式访问项目中的资源,例如图片、字体、颜色、XIB 文件等。通过 R.swift,你可以避免字符串类型的错误,提升代码的可维护性。 以下是 R.swift 库的详细用法: 1. 安装 R.swift 使用 Sw…...

Redis高危漏洞-GHSA-whxg-wx83-85p5:用户可能会使用特制的 Lua 脚本来触发堆栈缓冲区溢出

官方漏洞描述&#xff1a;https://github.com/redis/redis/security/advisories/GHSA-whxg-wx83-85p5 Redis 是一个高性能的键值数据库&#xff0c;广泛用于缓存和存储数据。由于其功能丰富&#xff0c;Redis 允许用户通过 Lua 脚本来执行服务器端的操作。Lua 脚本通常用来在 …...

分组通道自注意力G-CSA详解及代码复现

G-CSA定义 G-CSA (Grouped Channel Self-Attention) 是一种创新性的视觉注意力机制,巧妙地结合了卷积和自注意力的优势。通过将输入特征图划分为多个独立的通道组,在每个组内执行自注意力操作,G-CSA实现了高效的全局信息交互,同时保留了局部特征细节。这种方法不仅提高了模…...

Unity 自定义批量打包工具

打包配置项 using UnityEngine; using System.Collections.Generic;namespace MYTOOL.Build {[System.Flags]public enum VersionOptions{None 0,Major 1,Minor 4,Build 8,Revision 0x10,}/// <summary>/// 批量打包配置文件/// </summary>[CreateAssetMenu]…...

WebGL性能检测

WebGL性能检测系统说明 检测维度 1. WebGL版本支持检测(20分) WebGL 1.0 和 WebGL 2.0 版本检测WebGL 2.0 支持得20分仅支持WebGL 1.0 得12分主要影响高级特性和性能优化的可用性2. GPU性能评估(25分) 通过WEBGL_debug_renderer_info获取显卡信息根据GPU品牌和型号进行评…...

C#,图论与图算法,输出无向图“欧拉路径”的弗勒里(Fleury Algorithm)算法和源程序

1 欧拉路径 欧拉路径是图中每一条边只访问一次的路径。欧拉回路是在同一顶点上开始和结束的欧拉路径。 这里展示一种输出欧拉路径或回路的算法。 以下是Fleury用于打印欧拉轨迹或循环的算法&#xff08;源&#xff09;。 1、确保图形有0个或2个奇数顶点。2、如果有0个奇数顶…...

Jenkins触发器--在其他项目执行后构建

前言&#xff1a; jenkins中有多种触发器可用&#xff0c;可以方便的控制构建的启动 这里简单介绍下项目后构建的配置方法 1. 解释&#xff1a; Build after other projects are built Set up a trigger so that when some other projects finish building, a new build is…...

UE5.4运行报错解决(关于osg使用-无法解决的外部命令)(未解决)

报错如下&#xff1a; 09:38:06:665 4>EpicGames.Core -> E:\AppInstall\EpicGames\UE_5.4\Engine\Source\Programs\Shared\EpicGames.Core\bin\Development\net6.0\EpicGames.Core.dll 09:38:06:668 5>------ 已启动全部重新生成: 项目: EpicGames.MsBuild, 配…...

Swift语言的软件工程

Swift语言的软件工程 引言 随着科技的不断进步&#xff0c;软件开发行业正在经历着前所未有的变化。在这场变革中&#xff0c;Swift语言作为苹果公司推出的一种新型编程语言&#xff0c;凭借其简洁、高效及安全的特性&#xff0c;正在快速崛起&#xff0c;成为现代软件工程中…...

国内外网络安全政策动态(2024年12月)

▶︎ 1.2项网络安全国家标准获批发布 2024年12月6日&#xff0c;根据2024年11月28日国家市场监督管理总局、国家标准化管理委员会发布的中华人民共和国国家标准公告&#xff08;2024年第29号&#xff09;&#xff0c;全国网络安全标准化技术委员会归口的2项网络安全国家标准正…...

DELTA并联机械手视觉方案荣获2024年度机器人应用典型案例奖

直击现场 2025年1月9日晚&#xff0c;2024深圳市机器人年度评选颁奖典礼在深圳市南山区圣淘沙酒店正式拉开帷幕。本次颁奖活动由中国科学院深圳先进技术研究院指导&#xff0c;深圳市机器人协会与《机器人与智能系统》杂志组织承办。 正运动公司受邀参与此次典礼&#xff0c;…...

python 3个线程轮流打印A、B、C

要实现 Python 中三个线程轮流打印 A、B、C 的效果&#xff0c;可以使用 threading 模块和 Condition 或 Lock 来同步线程。以下是使用 Condition 的解决方案&#xff1a; 代码实现 import threading# 初始化条件变量 condition threading.Condition() current 0 # 共享变…...

Http 响应状态码 前后端联调

http 响应状态码 &#xff1a;是服务器在处理HTTP请求时返回的状态信息&#xff0c;用于表示请求的处理结果 1xx : 信息性状态码 100 Continue: 服务器已收到请求头部&#xff0c;客户端应继续发送请求体。 101 Switching Protocols : 切换协议。服务器已理解客户端的请求&a…...

AI Agent:软件测试自动化的新纪元

在信息技术日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;技术的蓬勃发展正引领着各个行业的深刻变革&#xff0c;软件测试领域同样迎来了前所未有的机遇与挑战。AI Agent&#xff0c;这一融合了先进机器学习与自然语言处理技术的智能实体&#xff0c;正悄然成…...