手写Java线程池与定时器:彻底掌握多线程任务调度
目录
一、线程池
1.1、什么是线程池
1.2、Java标准库中的线程池
1.3、ThreadPoolExecutor的七大参数
1.4、模拟实现线程池
1.4.1、submit ()
1.4.2、构造方法
1.4.3、运行结果
二、定时器
2.1、标准库中的定时器
2.2、模拟实现定时器
2.2.1、MyTimerTask类
2.2.2、MyTimer类
2.2.3、main方法
一、线程池
1.1、什么是线程池
线程池是一种线程管理技术,用于管理和复用线程。它会预先创建一定数量的线程把他们放入一个池中,当需要执行任务时,它会从线程池中获取空闲的线程来执行任务,执行完任务后,线程又会返回到线程池中等待下一个任务,这样可以避免频繁的创建和销毁线程,有效提高了系统的性能。
1.2、Java标准库中的线程池
Executors.newFixedThreadPool(2) 创建出含有两个线程的线程池
pool.submit()向线程池中提交一个任务
Executors.newFixedThreadPool(2) 方法创建的是使用前台线程的线程池。
public static void main(String[] args) {ExecutorService pool= Executors.newFixedThreadPool(2);pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("提交任务...");}});}
Executors创建线程池的几个方式:
Executors类 是对 ThreadPoolExecutor 类进行了一层封装和简化,隐藏了一些复杂性,使得开发者更容易使用线程池功能。
1.3、ThreadPoolExecutor的七大参数
核心线程数(corePoolSize):线程池中一直存活的线程数量,包括处于空闲状态的
最大线程数(maximumPoolSize):线程池中允许存在的最大线程数量,核心线程+临时线程
线程空闲时间(keepAliveTime):临时线程允许空闲的最大时间
线程空闲时间单位(unit):空闲时间单位
任务队列(workQueue):用于保存等待执行的任务的队列
线程工厂(threadFactory):用于创建新线程的工厂
拒绝策略(RejectedExecutionHandler):当线程池已经饱和且无法接受新任务时,用于处理新任务的策略
AbortPolicy( 默认策略):线程池已满且无法接受新任务时,抛出异常,拒绝任务
CallerRunsPolicy :线程池已满时,使调用线程(提交任务的线程)直接执行被拒绝的任务
DiscardPolicy :线程池已满时,直接丢弃新任务,不做任何处理
DiscardOldestPolicy :线程池已满时,丢弃队列中等待时间最长的任务,然后尝试将新任务放入队列中
1.4、模拟实现线程池
public class MyThreadPool {private BlockingDeque<Runnable> deque=null; //任务队列public MyThreadPool(int n) {this.deque = new LinkedBlockingDeque<>(n);for (int i = 0; i < n; i++) {Thread t = new Thread(() -> {try {while (true) {Runnable task = deque.take();task.run();}} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}}public void submit (Runnable task1) throws InterruptedException {deque.put(task1);}
}
class Main{public static void main(String[] args) throws InterruptedException {MyThreadPool myThreadPool=new MyThreadPool(10);for (int i = 0; i < 100; i++) {int id=i;myThreadPool.submit(()->{System.out.println(Thread.currentThread().getName()+" 在执行任务:"+id);});}}
}
1.4.1、submit ()
注意:队列中任务类型是Runnable类型
1.4.2、构造方法
1.4.3、运行结果
二、定时器
2.1、标准库中的定时器
在Java中,定时器(Timer)是一种用于调度和执行任务的机制。下面代码所以Timer 和TimerTask实现一个定时任务,schedule里面传入两个参数(1)需要执行的任务代码 (2)指定多长时间之后执行
public static void main(String[] args) {Timer timer=new Timer();TimerTask timerTask=new TimerTask() {@Overridepublic void run() {System.out.println("3秒后执行此任务...");}};timer.schedule(timerTask,3000);}
2.2、模拟实现定时器
要模拟实现上述定时器,我们需要实现以下几点:
1️⃣:创建一个可以表示任务的类
2️⃣:能够管理多个任务的集合类
3️⃣:实现 schedule 方法把任务添加到队列中
4️⃣:创建额外的线程执行任务
2.2.1、MyTimerTask类
class MyTimerTask implements Comparable<MyTimerTask>{private long time;private Runnable task;public MyTimerTask(Runnable task,long time){this.task=task;this.time=time;}@Overridepublic int compareTo(MyTimerTask o) {//重写,进行时间上的比较return Long.compare(this.time,o.time);}public long getTime() {return time;}public void run(){task.run();}
}
MyTimerTask 为表示任务的类,成员变量包含指定的时间和需要执行的任务,在构造方法中传入时间和Runnable类型的任务,重写compare方法为了仅比较MyTimerTask对象中的time变量的大小
2.2.2、MyTimer类
class MyTimer{public PriorityQueue<MyTimerTask> queue=new PriorityQueue<>();//集合类Object locker=new Object();//锁对象public MyTimer(){Thread t=new Thread(()->{try {while (true) {synchronized (locker){while (queue.isEmpty()) {//队列为空时locker.wait();}MyTimerTask myTimerTask = queue.peek();if (myTimerTask.getTime() > System.currentTimeMillis()) {//队列不为空,但时间未到locker.wait(myTimerTask.getTime()-System.currentTimeMillis());//等待时间差} else {myTimerTask.run();queue.poll();}}}}catch (InterruptedException e){e.printStackTrace();}});t.start();}public void schedule(Runnable task,long delay){ //将任务添加到队列中synchronized (locker){MyTimerTask timetask=new MyTimerTask(task,delay+System.currentTimeMillis());queue.offer(timetask);locker.notifyAll();}}
}
下述任务队列我们采用优先级队列,为什么不使用ArrayList或其他数据结构呢?主要原因还是要向任务队列传入两个参数,其中一个为时间,我们需要按任务时间的长短进行排序, 倘若使用ArrayList我们每次执行任务时,就需要遍历整个线性表找到时间最短的任务,实在太麻烦~~,不如在插入任务时就排序成有序队列,所以采用优先级队列。
最近几次使用synchronized时搭配while循环是一种防御性编程策略,二次校验,阻塞等待唤醒,但下面的 if 语句不可替换,我们需要按实际需求来使用比较适合的方案。
schedule方法如下
2.2.3、main方法
public class Demo19 {public static void main(String[] args) {MyTimer myTimer=new MyTimer();myTimer.schedule(new MyRunable(){@Overridepublic void run() {System.out.println("3000ms秒后执行");}},3000);myTimer.schedule(new MyRunable(){@Overridepublic void run() {System.out.println("2000ms秒后执行");}},2000);myTimer.schedule(new MyRunable(){@Overridepublic void run() {System.out.println("1000ms秒后执行");}},1000);}
}
我们向任务队列中提交三个任务,分别在1、2、3秒后执行,执行程序,运行结果如图:
上述代码就是我们实现的简单的定时器,但是比起Java标准库中自带的定时器,缺陷还是很多的,但是底层逻辑大似相同,另外该定时器是一个额外的线程来按时间大小执行队列中的任务,但是如果同一时间,有大量任务添加到队列中,我们此处的单一线程中同一时间恐怕执行不了如此多的任务。比如中12:00,突然有1000000~个滑稽🤪提交了需要立马执行的任务:
这时我们可以使用线程池,让一个线程负责扫描,将需要执行的任务添加到线程池的任务队列中,让多个线程负责执行。
相关文章:
手写Java线程池与定时器:彻底掌握多线程任务调度
目录 一、线程池 1.1、什么是线程池 1.2、Java标准库中的线程池 1.3、ThreadPoolExecutor的七大参数 1.4、模拟实现线程池 1.4.1、submit () 1.4.2、构造方法 1.4.3、运行结果 二、定时器 2.1、标准库中的定时器 2.2、模拟实现定时器 2.2.1、MyTimerTask类 2…...
【科研绘图系列】R语言绘制区间点图(dot plot)
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图1画图2输出图片系统信息介绍 【科研绘图系列】R语言绘制区间点图(dot plot) 加载R包 library(tidyverse) library(ggtext) library(r…...
【Agent实战】从0到1开发一个Python 解释器 MCP SSE Server
写在前面 想象一个场景:LLM Agent(如 AutoGPT、MetaGPT 或我们自己构建的 Agent)在规划任务后,决定需要运行一段 Python 代码来处理数据或调用某个 API。它不能直接在自己的环境中执行(通常不具备这个能力,也不安全),而是需要将这段代码发送给一个专门的外部服务来执行…...
C语言大写转小写2.0
一、阐述关系 上一次的题目是大写转小写,这一次代码不一样,运行的结果也不一样,这次的代码在此基础之上改动了一下,虽然看起来相似,但实际上运行结果不一样 二、题目展示 下面代码中,运行的结果是多少? 三、分析过程 首先,进入main函数,先声明了一个字符型数组是"012…...
pnpm常见报错解决办法
PS D:\code\gitlab\manus-web> pnpm add -D types/framer-motion --save-exact --config.strict-peer-depsfalse Debugger attached. WARN deprecated eslint8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other op…...
【Linux网络】:套接字之UDP
一、UDP和TCP协议 TCP (Transmission Control Protocol 传输控制协议)的特点: 传输层协议有连接(在正式通信前要先建立连接)可靠传输(在内部帮我们做可靠传输工作)面向字节流 UDP (U…...
量子威胁下的安全革命:后量子密码学技术路线与迁移挑战全解析
引言 量子计算技术的快速发展正在重塑现代密码学的安全版图。随着Shor算法对传统公钥密码体系的根本性威胁[1],全球范围内后量子密码学(Post-Quantum Cryptography, PQC)的研究与标准化进程已进入关键阶段。 本文基于权威文献分析,…...
多模态大语言模型(MLLM)- kimi-vl technical report论文阅读
前言 kimi-vl是月之暗面团队于2025年4月10日发布的多模态大模型。 代码链接:https://github.com/MoonshotAI/Kimi-VL 背景 随着人工智能技术的快速发展,人们对AI助手的需求已从单一文本交互转向多模态理解。新一代多模态模型如GPT-4o和Gemini虽展现…...
ai聊天流式响应,阻塞式和流式响应 nginx遇到的坑
问题 现在做ai的流式请求,在开发环境使用代理访问接口,显示是正常的。上到正式环境,代理通过nginx配置可以访问到流式接口。在本地测试postman请求流式接口,返回的东西是流式返回, 在正式环境里面使用postman请求流式…...
Linux安全模块:SELinux与AppArmor深度解析
引言 在Linux安全领域,SELinux和AppArmor就像两位忠诚的"系统保镖"💂,为你的服务器提供强制访问控制(MAC)保护!本文将深入解析这两大安全模块的工作原理、配置方法和实战技巧。无论你是要加固Web服务器,还是…...
FlinkJobmanager深度解析
1. JobManager 概述 Flink 是一个分布式流处理框架,其核心组件包括 JobManager、TaskManager 和客户端(如 CLI 或 Web UI)。JobManager 是 Flink 集群的“大脑”,负责协调作业的整个生命周期,包括作业调度、资源管理、…...
FlinkSql入门与实践
一、为什么需要 Flink SQL? 传统 SQL 是面向静态数据的查询语言,而现代实时业务要求对动态数据流进行即时分析。Flink SQL 应运而生,它让开发者无需编写复杂的状态管理代码,就能实现实时ETL、复杂事件处理(CEP&#x…...
【物联网】基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版)
演示视频: 基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版) 前言:本设计是基于ThingsCloud云平台版,还有另外一个版本是基于机智云平台版本,两个设计只是云平台和手机APP的区别,其他功能都一样。如下链接: 【物联网】基于LORA组网的远程环境监测系统设计(机…...
C++中指针Ptr(一级指针、二级指针)的基本使用详解(1)
C 中的指针是非常强大的工具,理解一级指针、二级指针以及它们与数组的关系,对于写出高效且安全的程序非常重要。下面我将从基础讲起,详细解释 一级指针、二级指针 的使用,注意事项,以及它们和数组之间的联系与区别&…...
科技赋能建筑新未来:中建海龙模块化建筑产品入选中国建筑首批产业化推广产品
在建筑工业化浪潮中,中国建筑国际集团旗下中建海龙科技有限公司(以下简称“中建海龙”)致力以科技创新赋能传统建造转型升级,大力发展新质生产力,促进科技成果在建筑产业体系化、规模化应用,面向“产品化、…...
示例:Spring JDBC 声明式事务(xml配置形式)
声明式事务是指在不修改源代码的情况下通过配置applicationContext.xml自动实现事务控制,其本质是AOP环绕通知。它的触发时机为:1、当目标方法执行成功时自动提交事务,2、当目标方法抛出运行时异常时,自动事务回滚 核心步骤示例&a…...
java多线程(7.0)
目录 编辑 定时器 定时器的使用 三.定时器的实现 MyTimer 3.1 分析思路 1. 创建执行任务的类。 2. 管理任务 3. 执行任务 3.2 线程安全问题 定时器 定时器是软件开发中的一个重要组件. 类似于一个 "闹钟". 达到一个设定的时间之后, 就执行某个指定好的…...
sgpt在kali应用
Kali Linux 下 sgpt 渗透测试相关案例 1. 扫描目标主机存活 sgpt -s "使用 nmap 扫描 192.168.1.100 是否存活"示例命令: nmap -sn 192.168.1.1002. 扫描目标主机开放端口和服务 sgpt -s "使用 nmap 扫描 192.168.1.100 常见端口和服务"示例…...
小白电路设计-设计11-恒功率充电电路设计
介绍 作为电子信息工程的我,电路学习是一定要学习的,可惜目前作为EMC测试工程师,无法兼顾太多,索性不如直接将所学的知识进行运用,并且也可以作为契机,进行我本人的个人提升。祝大家与我一起进行提升。1.本…...
express的模板handlebars用app.engine()创建配置和用exphbs.create()的区别
在使用 express-handlebars 时,app.engine 和 exphbs.create 都可以用来配置 Handlebars 模板引擎,但它们的使用方式和功能有一些区别。以下是详细的对比和说明 app.engine 方法 app.engine 是 Express 提供的方法,用于注册一个新的模板引擎…...
【Python数据库与后端开发】从ORM到RESTful API
目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心代码实现案例1:SQLAlchemy模型定义案例2:FastAPI异步接口案例3:连接池配…...
数据结构(java)二叉树的基本操作
1.二叉树的性质: 1.若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2*-1(i>0)个结点 2.若规定只有根节点的二叉树的深度为1,则深度为K的二叉树的最大结点数是2都k次方-1 3.对于任何一个二叉树,如果其叶结点个数为 n…...
windows编程字符串处理
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、windows常用字符出处理函数?二、测试代码总结 前言 提示:这里可以添加本文要记录的大概内容: Windows编程中主要使用两…...
CentOS系统防火墙服务介绍
CentOS 系统使用的是 firewalld 防火墙服务(从 CentOS 7 开始),它基于 zone(区域) 和 service(服务) 的机制来配置网络访问控制,替代了传统的 iptables。 iptables 是 Linux 系统中…...
59、微服务保姆教程(二)Nacos--- 微服务 注册中心 + 配置中心
Nacos— 微服务 注册中心 + 配置中心 一.什么是Nacos? Nacos是阿里的一个开源产品,是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案。 Nacos核心定位是“一个更易于帮助构建云原生应用的动态服务发现、配置和服务管理平台”,也就是我们的注册中心和配…...
Git命令行中vim的操作
Git命令行用vim打开文件,或者用其他git命令打开了文件,需要编辑和保存文件等,有些命令表情奇怪,往往容易忘记这些命令。记录下。 下面这篇比较实用和简练: gitvim编辑文件命令 • Worktile社区https://worktile.com/…...
【分布式系统中的“瑞士军刀”_ Zookeeper】一、Zookeeper 快速入门和核心概念
在分布式系统的复杂世界里,协调与同步是确保系统稳定运行的关键所在。Zookeeper 作为分布式协调服务的 “瑞士军刀”,为众多分布式项目提供了高效、可靠的协调解决方案。无论是在分布式锁的实现、配置管理,还是在服务注册与发现等场景中&…...
【昇腾】【训练】800TA2-910B使用LLaMA-Factory训练Qwen
文章目录 1. 使用docker安装1.1 配置docker1. 2 拉取 LLaMA-Factory1.3 修改配置 2. 下载模型3. 准备训练数据3.1 下载数据集3.2 自定义数据集配置 4. 训练4.1 训练配置4.2 启动训练4.3 训练效果测试 5. 合并权重 更好的阅读体验:传送门 服务器:800TA2 芯…...
Python自动化解决滑块验证码的最佳实践
1. 引言:滑块验证码的挑战与自动化需求 滑块验证码(Slider CAPTCHA)是当前互联网广泛使用的反爬机制之一,它要求用户手动拖动滑块到指定位置以完成验证。这种验证方式可以有效阻止简单的自动化脚本,但对爬虫开发者来说…...
知识蒸馏和迁移学习的区别
知识蒸馏和迁移学习虽然都涉及知识的传递,但并不是同一个概念,它们在目的、方法和应用场景上有显著区别: 1. 定义与核心思想 迁移学习(Transfer Learning) 是一种广义的机器学习范式,核心是将从一个任务或领…...
二项分布详解:从基础到应用
二项分布详解:从基础到应用 目录 引言二项分布的定义概率质量函数及其证明期望与方差推导二项分布的重要性质常见应用场景与其他分布的关系知识梳理练习与思考 引言 概率论中,二项分布是最基础也是最常用的离散概率分布之一。它描述了在固定次数的独…...
迁移学习(基础)
迁移学习理论 目标 迁移学习中的有关概念掌握迁移学习的两种方式 概念 预训练模型微调微调脚本 预训练模型(Pretrained model) 一般情况下预训练模型都是大型模型, 具备复杂的网络结构, 众多的参数量, 以及足够大的数据集进行训练而产生的模型, 在NLP领域, 预训练模型往往…...
云服务器和独立服务器的区别在哪
在当今数字化的时代,服务器成为了支撑各种业务和应用的重要基石。而在服务器的领域中,云服务器和独立服务器是两个备受关注的选项。那么,它们到底有何区别呢? 首先,让我们来聊聊成本。云服务器通常采用按需付费的模式…...
大模型时代的深度学习框架
作者:算力魔方创始人/英特尔创新大使刘力 在CNN时代,AI模型的参数规模都在百万级别,仅需在单张消费类显卡上即可完成训练。例如,以业界知名的CNN模型:ResNet50为例,模型参数量是约为 25.63M,在…...
BIOS主板(非UEFI)安装fedora42的方法
BIOS主板(非UEFI)安装fedora42的方法 现实困难:将Fedora-Workstation-Live-42-1.1.x86_64.iso写入U盘制作成可启动U盘启动fedora42,按照向导将fedora42安装到真机的sda7分区中得到报错如下内容: /boot/efi 必需的 /boot/efi必须位于格式化为e…...
C# 综合示例 库存管理系统7 主界面(FormMain)
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 图99A-22 主界面窗口设计 主界面是多文档界面容器,需要将窗体属性IsMdiContainer设置为True。关于多文档界面编程请参看教程第7.12节《多文档界面》。 主界面并不提…...
1、RabbitMQ的概述笔记
一、什么是RabbitMQ Rabbit是一个公司名.MQ(nessage queue) 消息队列的意思,RabbitMQ 是 Rabbit企业下的一个消息队列产品。 RabbitMQ 是⼀个实现了 AMQP 的 消息队列 服务,是当前主流的消息中间件之⼀. AMQP:即Advanced MessageQueuingProtocol(高级…...
使用spring boot vue 上传mp4转码为dash并播放
1.前端实现 <template><div class"video-upload"><el-uploadclass"upload-demo"action"/api/upload":before-upload"beforeUpload":on-success"handleSuccess":on-error"handleError":show-file-…...
C++智能指针概念理解的面试题
C智能指针概念理解的面试题 第一部分:基础概念 解释std::unique_ptr和std::shared_ptr在以下方面的区别: 所有权语义性能开销自定义删除器的存储方式是否支持数组类型 答案: 所有权语义: unique_ptr:独占所有权&#…...
52.[前端开发-JS实战框架应用]Day03-AJAX-插件开发-备课项目实战-Lodash
常用JavaScript库 1 认识前端工具库 前端工具类库 2 Lodash vs underscore underscore库 VS Lodash库 Lodash库 的安装 Lodash库字符串、数组 Lodash库对象、集合、函数 3 Day.js vs Mement Moment.js库 VS Day.js库 Day.js库安装 Day.js获取、设置、操作时间 Day.js解析、…...
【论文阅读】平滑量化:对大型语言模型进行准确高效的训练后量化
论文题目:SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 论文地址:[2211.10438] SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 代码地址:http…...
mysql游标分页详解:让分页又快又稳的终极方案
一、什么是游标分页? 游标分页是一种更高效的分页方式,它通过"记住当前位置"而不是"数页码"来实现分页。就像看书时夹书签一样,游标分页会记住你看到哪里了,下次直接从那里继续。 传统分页 vs 游标分页 传…...
图论---染色法(判断是否为二分图)
O(nm) 二分图:可以把所有的点划分到两边,使得边只在集合之间,集合内部没有边。 二分图当且仅当图中不含奇数环(边数为奇数条) #include <iostream> #include <vector> #include <cstring> using …...
算法 | 基于SSA-CNN-LSTM(麻雀算法优化卷积长短期记忆神经网络)的股票价格预测(附完整matlab代码,公式,原理,可用于毕业论文设计)
以下是一个基于SSA-CNN-LSTM(麻雀算法优化卷积长短期记忆神经网络)的股票价格预测MATLAB项目实例,包含完整代码和详细注释。代码分为数据预处理、模型构建、优化算法、训练预测四个部分。 🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜 1. 数据预处理 %% 数据加…...
在html中如何创建vue自定义组件(以自定义文件上传组件为例,vue2+elementUI)
1、先上代码:vueUpload.js var dom <div class"upload-file"><el-upload :action"uploadFileUrl" :before-upload"handleBeforeUpload" :file-list"fileList" :limit"limit":on-error"handleUpl…...
Asp.Net Core 基于(asp.net core 2.2) 创建asp .net core空项目
文章目录 ASP.NET Core 应用程序的标准入口点,用于配置和启动一个 Web 主机(WebHost)。`InProcess` 代码分析解决 HTTP Error 500.31 - Failed to load ASP.NET Core runtime 的完整方案**`launchSettings.json` 配置文件分析**ASP.NET Core 中的配置源详解ASP.NET Core 应用…...
AiFlutter 低代码平台介绍
产品概述 AiFlutter 低代码平台是一款基于拖拽组件和配置流程图的可视化开发工具,旨在简化移动应用开发过程。无需编写代码,用户即可通过拖拽组件快速搭建应用界面,并通过配置流程图设计页面逻辑。平台支持硬件通信功能,用户可直…...
Flutter Dart 集合类型List Set Map详解军 以及循环语句 forEaclh map where any every
List基础用法 var list1 ["西瓜", "苹果", "香蕉", true, 0];var list2 <String>["西瓜", "苹果", "香蕉"];List list3 ["西瓜", "苹果", "香蕉"];list3.add("草莓&…...
aws(学习笔记第三十九课) iot-msk-pipeline
文章目录 aws(学习笔记第三十九课) iot-msk-pipeline学习内容:1. 整体架构1.1 代码链接1.2 代码调整1.2 整体架构(概要)1.3 整体架构(详细) 2. 代码解析2.1 创建IotProducerDestination2.2 创建IotProducer2.3 创建MSK client的EC22.4 创建MSK cluster2.5 创建Main …...
2025上海车展:赛轮思AI携手行业领军企业展示xUI——混合式、智能体化的AI助理平台
用户将可首次全面体验集成多模态SLM (端侧大语言模型)的Cerence xUl,此次演示由长城汽车和TCL合作呈现 马萨诸塞州伯灵顿,2025年4月22日——Cerence Inc.(NASDAQ: CRNC)(“赛轮思AI”),全球对话…...