Java EE(8)——线程安全总结(翻新版)——定时器(Timer)线程池(ThreadPoolExecutor)
1.Timer
1.1Timer基本介绍
1.Timer的主要作用
任务调度:Timer允许你安排一个任务在未来的某个时间点执行,或者以固定的间隔重复执行
后台执行:Timer可以使用一个后台线程来执行任务,这意味着调度和执行任务不会阻塞主线程(主线程结束后后台线程跟着结束)
简单易用:Timer提供了一个相对简单的方式来处理定时任务,适合用于不需要复杂调度的场景
2.Timer的构造方法
//1.默认构造方法
//创建一个Timer对象,是一个后台线程,并使用线程的默认名字
public Timer() {this("Timer-" + serialNumber());
}
//2.指定线程名字的构造方法
//创建一个Timer对象,是一个后台线程,并使用指定的线程名字
public Timer(String name) {thread.setName(name);thread.start();
}
//3.指定是否为后台线程的构造方法
//传入true,是后台线程;传入false,是前台线程
public Timer(boolean isDaemon) {this("Timer-" + serialNumber(), isDaemon);
}
//4.指定线程名字和是否为后台线程的构造方法
public Timer(String name, boolean isDaemon) {thread.setName(name);thread.setDaemon(isDaemon);thread.start();
}
3.Timer中的schedule方法
(1)schedule(TimerTask task, Date time):安排任务在指定的时间执行一次
public static void main(String[] args) {Timer timer = new Timer();TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("延迟三秒执行");}};//使用Date对象来指定具体的执行时间//new Date(System.currentTimeMillis()+1000表示当前时间等待1000mstimer.schedule(timerTask,new Date(System.currentTimeMillis()+1000));
}
(2)schedule(TimerTask task, Date firstTime, long period):安排任务在指定的时间首次执行,然后每隔一段时间重复执行
public static void main(String[] args) {Timer timer = new Timer();TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("延迟三秒执行");}};//当前时间等待1000ms后第一次执行任务//此后每间隔1000ms就执行一次任务timer.schedule(timerTask,new Date(System.currentTimeMillis()+1000),1000);
}
(3)schedule(TimerTask task, long delay):安排任务在指定的延迟时间后执行一次(相对于当前时间)
public static void main(String[] args) {Timer timer = new Timer();TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("延迟三秒执行");}};//当前时间延迟3000ms后执行timer.schedule(timerTask,3000);
}
(4)schedule(TimerTask task, long delay, long period):安排任务在指定的延迟时间后首次执行,然后每隔一段时间重复执行
public static void main(String[] args) {Timer timer = new Timer();TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("延迟三秒执行");}};//当前时间延迟3000ms后执行//此后每间隔3000ms就执行一次任务timer.schedule(timerTask,3000,3000);
}
问题:上述构造方法中,使用Date对象指定时间和使用long类型数据指定时间有什么区别?
Date对象可以指定一个具体的时间,比如在2025年1月1日12时01分01秒执行任务;
而传入一个long类型数据表示以当前时间为基准,延迟指定时间后执行任务
1.2模拟实现MyTimer
1.2.1大体框架
MyTimer类:
(1)Thread线程:用来执行任务
(2)PriorityQueue(小根堆):存放任务,并且可以按照时间先后顺序取出任务
(3)MyTimer构造方法:启动thread
(4)schedule:实例化/添加任务
任务
MyTask类
(1)time:保存任务要执行的时间
(2)Runnable:重写run方法
(3)run方法:执行run方法
(4)getTime:获取人物的执行时间
(5)compareTo方法:保证放进小根堆的任务必须是可比较的
1.2.2MyTask类
1.2.3MyTime类
1.2.4代码演示
1.3MyTimer源码
import java.util.PriorityQueue;
/*** Created with IntelliJ IDEA.* Description:* User: 38917* Date: 2025-03-05* Time: 19:26*/
//描述一个任务
class MyTimerTask implements Comparable<MyTimerTask>{private final long time;private final Runnable runnable;public MyTimerTask(Runnable runnable,long delay){this.runnable = runnable;this.time = (System.currentTimeMillis() + delay);}//执行run中的代码块public void run(){runnable.run();}//比较@Overridepublic int compareTo(MyTimerTask o) {return (int)(this.time - o.time);}//获取时间public long getTime() {return time;}
}class MyTimer {//创建线程Thread thread;//存放任务private final PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();//创建锁对象private final Object locker = new Object();//实例化任务public void schedule(Runnable runnable,long delay){synchronized (locker) {//实例化任务MyTimerTask myTimerTask = new MyTimerTask(runnable, delay);//添加任务queue.offer(myTimerTask);locker.notify();}}//扫描任务队列,执行任务的线程public MyTimer(){thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {//锁是保护队列try {synchronized (locker) {while (queue.isEmpty()) {locker.wait();}MyTimerTask myTimerTask = queue.peek();long curTime = System.currentTimeMillis();if (curTime >= myTimerTask.getTime()) {queue.poll();//执行任务myTimerTask.run();} else {locker.wait(myTimerTask.getTime() - curTime);}}} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread.setDaemon(true);thread.start();}
}public class Main {public static void main(String[] args) throws InterruptedException {MyTimer myTimer = new MyTimer();myTimer.schedule(() -> System.out.println("400"),400);myTimer.schedule(() -> System.out.println("300"),300);myTimer.schedule(() -> System.out.println("200"),200);myTimer.schedule(() -> System.out.println("100"),100);Thread.sleep(500);System.out.println("Hello Main");}
}
2.线程池
2.1什么是线程池?
1.概念:线程池是一种管理和复用线程的编程模式。它预先创建一定数量的线程,在执行任务需要时,将任务分配给这些线程,从而提高运行效率
2.主要特点
线程复用:当线程执行完一个任务时,不会立即销毁,而是等待下一个任务的到来(当然这种等待是有时间限制的),这样避免了频繁的创建和销毁线程
动态调整:根据实际环境需要动态调整线程数量,以达到最佳性能
任务队列:线程池会维护一个任务队列,用于存放待执行的任务,当线程空闲时,从队列中取出任务并执行
2.2 标准库线程池参数介绍
1.int corePoolSize:核心线程数
2.int maximumPoolSize:最大线程数
3.long keepAliveTime:非核心线程的空闲时的最大存活时间。假如corePoolSize=4,maximumPoolSize=8,有四个非核心线程,这类线程空闲时,不能一直等待新任务的到来,当等待时间超过keepAliveTime后就会销毁
4.TimeUnit unit:long keepAliveTime的时间单位
5.BlockingQueue workQueue:任务队列
6.ThreadFactory threadFactory:线程工厂,用于创建新线程的工厂
7.RejectedExecutionHandler handler拒绝策略
2.3线程池的执行流程
假设现在有一个线程池:
核心线程数2,最大线程数4,等待队列2
(1)任务数量<=2(A,B)时,由核心线程执行任务
(2) 2<任务数量<=4(A,B,C,D)时,核心线程无法同时处理所有任务,未被执行的任务(C,D)将会进入等待队列中等待核心线程执行
(3)4<任务数量<=6(A,B,C,D,E,F),此时等待队列也满了,线程池就会就会开放非核心线程来执行任务,C和D任务继续在等待队列中等待,新添加的E和F任务由非核心线程来执行
(4)任务数量>6,核心线程,等待队列,非核心线程都被任务所占用,仍然无法满足需求,此时就会触发线程池的拒绝策略
RejectedExecutionHandler handler四大拒绝策略
1.AbortPolicy:直接抛异常
2.CallerRunsPolicy:由提交该任务的线程来执行
3.DiscardPolicy:丢弃新任务
4.DiscardOldestPolicy:丢弃最老的任务
2.4模拟实现一个简单的线程池
3.线程安全问题总结
(1)使用没有共享资源的模型
(2)使用共享资源只读,不写的模型
-
不需要写共享资源的模型
-
使用不可变对象
(3)直面线程安全(重点)
-
保证原子性:synchronized
-
保证顺序性:volatile(取消指令重排序)
-
保证可见性:synchronized(上锁时将主内存中的数据同步到工作内存,解锁时将工作内存的数据同步到主内存),volatile(强制从主内存读取数据)
4.小结
基础的线程安全问题以及常见的四种设计模式(单例,生产者&消费者,定时器,线程池)至此全部都介绍完毕了,下节开始就从锁策略开始讲解
相关文章:
Java EE(8)——线程安全总结(翻新版)——定时器(Timer)线程池(ThreadPoolExecutor)
1.Timer 1.1Timer基本介绍 1.Timer的主要作用 任务调度:Timer允许你安排一个任务在未来的某个时间点执行,或者以固定的间隔重复执行 后台执行:Timer可以使用一个后台线程来执行任务,这意味着调度和执行任务不会阻塞主线程(主线程…...
#[特殊字符]Rhino建模教程 · 第一章:正方体建模入门
🦏Rhino建模教程 第一章:正方体建模入门 本章将从最基础的操作入手,带你一步步掌握Rhino建模的核心流程,适合新手或需要复习基础的用户。 🎯 目标:制作一个带凹槽、圆角、封盖的正方体模型,并…...
How to run ERSEM
Build ERSEM Make a “build” folder, and go into the build folder. Create “build_archer2.edit.sh” #!/usr/bin/env bash# Script for compiling FVCOM-FABM-ERSEM for ARCHER2 # # The build is split into three phases: # # 1) Build the FABM-ERSEM library. Her…...
关于QT5项目只生成一个CmakeLists.txt文件
编译器自动检测明明可以检测,Kit也没有报红 但是最后生成项目只有一个文件 一:检查cmake版本,我4.1版本cmake一直报错 cmake3.10可以用 解决之后还是有问题 把环境变量加上去:...
C++ string类
1.标准库中的string类 在 C 里,string类属于标准库的一部分,它在<string>头文件中定义,用于处理和操作字符串。 1.1string类的常用接口说明 1.1.1. string类对象的常见构造 string() (重点) 构造空的string类…...
如何使用ChatGPT撰写短视频爆款文案
短视频已经成为了互联网内容消费的重要形式,吸引观众的眼球成为内容创作者的首要任务。在短视频平台的内容过载中,如何写出一篇能够迅速吸引观众点击、分享并获得高互动的爆款文案,是每个短视频创作者都在追求的目标。今天,我们将…...
基于Tesseract与Opencv的电子发票识别[1]
本文我们将尝试使用tesseract识别电子发票上的信息并不断提高识别准确率,是一个逐渐调整的过程,仅用于记录研究过程。 图像识别:使用tesseract识别。图像预处理:使用OpenCV等图像处理库对发票图像进行预处理,如灰度化…...
数据库—函数笔记
一,数据库函数的分类 内置函数(Built-in Functions) 数据库系统自带的函数,无需额外定义即可直接调用。 聚合函数:对数据集进行计算(如 SUM, AVG, COUNT)。 字符串函数:处理文本数据…...
产品研发流程说明记录
1. 前言 在小型公司,产品研发流程通常较为简单,需求提出后经过简单评审便直接开发上线。而在中大型互联网公司,研发流程更加规范和系统,涉及多部门协作和多环节把控。本文将详细介绍一个标准的产品需求研发流程,帮助相…...
智慧城市:如同为城市装上智能大脑,开启智慧生活
智慧城市的概念随着信息技术的飞速发展而逐渐兴起,它通过集成物联网、大数据、人工智能和数字孪生等先进技术,为城市管理和居民生活带来了前所未有的智能化变革。本文将深入探讨这些核心技术及其在智慧城市的典型应用场景,展示智慧城市如何提…...
游戏测试入门知识
高内聚指的是一个模块或组件内部的功能应该紧密相关。这意味着模块内的所有元素都应该致力于实现同一个目标或功能,并且该模块应当尽可能独立完成这一任务。 低耦合则是指不同模块之间的依赖程度较低,即一个模块的变化对其它模块造成的影响尽可能小。理…...
Sentinel源码—2.Context和处理链的初始化二
大纲 1.Sentinel底层的核心概念 2.Sentinel中Context的设计思想与源码实现 3.Java SPI机制的引入 4.Java SPI机制在Sentinel处理链中的应用 5.Sentinel默认处理链ProcessorSlot的构建 4.Java SPI机制在Sentinel处理链中的应用 (1)初始化Entry会初始化处理链 (2)初始化处…...
Java基础第20天-JDBC
JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题,程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作 ResultSet 表示数据库结果集的数据表,通常通过执行查询数据库的语句生…...
VMware下Ubuntu空间扩容
目的: Ubuntu空间剩余不足,需要对Ubuntu进行扩容。 使用工具: 使用Ubuntu系统中的gparted工具进行系统扩容。 前提: 1、电脑有多余的未分配磁盘空间,比如我的Ubuntu磁盘G盘是200G,现在快满了,…...
第十一章 网络编程
在TCP/IP协议中,“IP地址TCP或UDP端口号”唯一标识网络通讯中的一个进程。 因此可以用Socket来描述网络连接的一对一关系。 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)…...
Bad Request 400
之前一直以为400就是前端代码有问题 这下遇到了,发现是因为前后端不一致 后端代码注意:现在我写的int 前端请求 原因 :前后端不一致 💡 问题核心:后端 amount 类型是 int,但前端传了小数 237.31...
行业深度:金融数据治理中的 SQL2API 应用创新
金融行业作为数据密集型领域,面临着监管合规要求严苛、数据交互频次高、安全风险防控难度大等多重挑战。SQL2API 技术通过 “数据服务化 合规化” 的双重赋能,成为金融机构破解数据治理难题的核心工具,在多个关键场景实现突破性创新。 &…...
记录学习的第二十六天
还是每日一题。 今天这道题有点难度,我看着题解抄的。 之后做了两道双指针问题。 这道题本来是想用纯暴力做的,结果出错了。😓...
MySQLQ_数据库约束
目录 什么是数据库约束约束类型NOT NULL 非空约束UNIQUE 唯一约束PRIMARY KEY主键约束FOREIGN KEY外键约束CHECK约束DEFAULT 默认值(缺省)约束 什么是数据库约束 数据库约束就是对数据库添加一些规则,使数据更准确,关联性更强 比如加了唯一值约束&#…...
数据库ocp证书是什么水平
专业知识与技能:OCP 证书是对持证人在 Oracle 数据库管理、安装、配置、性能调优、备份恢复等方面专业知识和技能的权威认证。它要求考生通过一系列严格的考试,包括理论知识和实际操作能力的考核,以证明其具备扎实的 Oracle 数据库专业知识和…...
1022 Digital Library
1022 Digital Library 分数 30 全屏浏览 切换布局 作者 CHEN, Yue 单位 浙江大学 A Digital Library contains millions of books, stored according to their titles, authors, key words of their abstracts, publishers, and published years. Each book is assigned an u…...
基于Python的PC控制Robot 小程序开发历程
1、Background:用万能语言Python进行Robot 的控制一直以来是我想做的事,刚好有机会付诸实践。Just Do It~ 2、Python 代码编写: import socket import time HOST "192.168.0.1" #IP PORT 2008 #Por…...
Coze平台技术解析:零代码AI开发与智能体应用实践
【资源软件】 伏脂撺掇蒌葶苘洞座 /835a36NvQn😕 链接:https://pan.quark.cn/s/5180c62aacf7 「微信被删好友检测工具」筷莱坌教狴犴狾夺郝 链接:https://pan.quark.cn/s/fe4976448ca1 HitPaw Watermark Remover 链接:https://pan…...
在 K8s 上构建和部署容器化应用程序(Building and Deploying Containerized Applications on k8s)
在 Kubernetes 上构建和部署容器化应用程序 Kubernetes 是一个用于管理容器化工作负载和服务的开源平台。它提供了一个强大的框架来自动化部署、扩展和管理容器化应用程序。本博客将指导您完成在 Kubernetes 上构建和部署容器化应用程序的过程,重点介绍技术方面并使…...
【教程】如何使用Labelimg查看已经标注好的YOLO数据集标注情况
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
**Windows 系统**的常用快捷键大全
以下是 Windows 系统的常用快捷键大全,涵盖日常操作、文件管理、窗口控制、系统功能等,助你大幅提升效率: 一、基础系统操作 Win:打开/关闭「开始菜单」Win E:打开「文件资源管理器」Win D:一键显示桌面…...
L1-025 正整数A+B
L1-025 正整数AB L1-025 正整数AB - 团体程序设计天梯赛-练习集 (pintia.cn) 题解 第一次做这道题时,没有注意到num1 和 num2 是在区间 [1, 1000] 内,num1和num2的长度应该是4位数并且num1和num2不能等于0,num1和num2不能大于1000。这两个…...
Go 语言的 map 在解决哈希冲突时,主要使用了链地址法同时参考了开放地址法的思想即每个桶的 8个 key val对是连续的
总结一下 Go map 的哈希冲突解决机制。 1. 哈希表结构: Go 语言的 map 底层有两个主要结构:hmap 和 bmap,它们分别负责管理整个 map 的元数据和存储键值对的桶。 hmap:包含 map 的元数据,如桶的数量、已插入的键值对…...
未支付订单如何释放库存
在电商或交易系统中,处理未支付订单的库存释放是典型的高并发场景问题。以下是结合 Java 技术栈的完整解决方案,涵盖 设计思路、技术实现、容错机制,并基于实际项目经验(如标易行平台的标书资源预约场景)进行分析: 一、核心设计原则 最终一致性:确保库存释放与订单状态的…...
HDFS Full Block Report超限导致性能下降的原因分析
文章目录 前言发现问题失败的为什么是FBR块汇报频率的变化为什么FBR会反复失败HDFS性能下降导致Yarn负载变高的形式化分析理解线程理解IO Wait理解HDFS性能下降导致Yarn负载和使用率增高 引用 前言 我们的Yarn Cluster主要用来运行一批由Airflow定时调度的Spark Job࿰…...
[Java实战经验]链式编程与Builder模式
目录 链式编程Builder模式 链式编程 链式编程(Fluent AP)是一种编程风格,它通过在同一个对象上连续调用多个方法来执行一系列操作(让方法返回对象本身(return this))。这种风格的编程使代码更加…...
TypeScript 快速上手--禹神
TypeScript 快速上手 🪩 禹神:三小时快速上手TypeScript,TS速通教程_哔哩哔哩_bilibili ⼀、TypeScript 简介 TypeScript 由微软开发,是基于 JavaScript 的⼀个扩展语⾔。 TypeScript 包含了 JavaScript 的所有内容,即: TypeScript 是 Jav…...
YOLOv2 快速入门与核心概念:更快、更准的目标检测利器
今天,我们就来聊聊 YOLO 系列的第二代—— YOLOv2,看看它是如何在速度的基础上,进一步提升检测精度的。 目标检测的重要性:让机器“看懂”世界 想象一下,自动驾驶汽车需要实时识别道路上的车辆、行人、交通标志&…...
Differentiable Micro-Mesh Construction 论文阅读
信息 2024 CVPR 论文地址 摘要 本文提出了一个可微分框架,用于将标准网格转换为Micro-mesh( μ \mu μ-mesh)这种非常高效的格式,与以前基于阶段的方法相比,提供了一个整体方案。 本文的框架为高质量的 μ \mu μ 网格生产提供了许多优势&…...
groovy运行poi包处理xlsx文件报NoClassDefFoundError
背景:简单的在java上运行poi包处理xlsx文件,正常解析。使用groovy执行相关xlsx文件解析的程序时,报错。报错日志: java.lang.NoClassDefFoundError: org/openxmlformats/schemas/spreadsheetml/x2006/main/CTExtensionList poi版…...
基于Espressif-IDE的esp32开发
日后填坑 新建工程 基本操作 创建一个工程 编译工程 下载程序 运行成功...
emotn ui桌面软件tv版下载安装教程-emotn ui桌面好用吗
在智能电视和电视盒子的使用场景中,一款出色的桌面软件能显著提升用户体验。Emotn UI桌面软件TV版就是这样一款备受关注的产品,与此同时,乐看家桌面也以其独特功能在市场中占据一席之地。接下来,我们将会详细介绍Emotn UI桌面软件…...
抖音ai无人直播间助手场控软件
获取API权限 若使用DeepSeek官方AI服务,登录其开发者平台申请API Key或Token。 若为第三方AI(如ChatGPT),需通过接口文档获取访问权限。 配置场控软件 打开DeepSeek场控软件,进入设置界面找到“AI助手”或“自动化”…...
机器学习中的距离度量与优化方法:从曼哈顿距离到梯度下降
目录 前言一、曼哈顿距离(Manhattan Distance):二、切比雪夫距离 (Chebyshev Distance):三、 闵可夫斯基距离(Minkowski Distance):小结四、余弦距离(Cosine Distance)五、杰卡德距离(Jaccard Distance)六、交叉验证方法6.1 HoldOut Cross-v…...
在GitHub action中使用添加项目中配置文件的值为环境变量
比如我项目的根目录有一个package.json文件,但是我想在工作流中使用某个值,例如使用version的值,就需要从package.json里面取出来,然后存储到环境变量中,供后续步骤使用这个值。 读值存储 读取项目根目录中的某个jso…...
MCP认证难题破解指南
一、MCP 认证体系与核心挑战 1.1 认证体系解析 MCP(Microsoft Certified Professional)作为微软认证体系的基础,覆盖操作系统、云服务、开发工具等核心领域。2025 年最新认证体系包含以下关键方向: Azure 云服务: 覆盖 Azure 虚拟机、容器化部署、云原生应用开发等核心技…...
STM32F407实现内部FLASH的读写功能
文章目录 前言一、FLASH 简介二、读数据三、写数据四、最终效果五、完整工程 前言 我们通过仿真器下到芯片的程序一般会保存到eflash里面,在我们的STM32F407里面这里的空间挺大的,我所使用的芯片型号是STM32F407ZGT6,FLASH 容量为 1024K 字节…...
沃尔玛墨西哥30分钟极速配送:即时零售战争中的「超导革命」
当全球电商还在争夺「次日达」话语权时,沃尔玛在墨西哥城投下「时空压缩弹」——30分钟极速配送服务上线首周,订单转化率较常规渠道提升270%,生鲜品类客单价突破87美元(墨西哥财政部2024Q2数据)。这场物流革命正在改写…...
html页面打开后中文乱码
在HTML页面中遇到中文乱码通常是因为字符编码设置不正确或者不一致。要解决这个问题,你可以按照以下步骤进行: 确认HTML文件的编码 确保你的HTML文件保存时使用的是UTF-8编码。大多数现代的文本编辑器和IDE(如Visual Studio Code, Sublime Te…...
MySQL中的公用表表达式CTE实战案例应用
很多同学不会使用MySQL中的公用表表达式,今天这篇文章详细为大家介绍一下。 基础概念: 公用表表达式:MySQL中的公用表表达式(Common Table Expressions,简称CTE)是一种临时的结果集,它可以在一…...
开源TTS项目GPT-SoVITS,支持跨语言合成、支持多语言~
简介 GPT-SoVITS 是一个开源的文本转语音(TTS)项目,旨在通过少量语音数据实现高质量的语音合成。其核心理念是将基于变换器的模型(如 GPT)与语音合成技术(如 SoVITS,可能指“唱歌语音合成”&am…...
从零开始:Python运行环境之VSCode与Anaconda安装配置全攻略 (1)
从零开始:Python 运行环境之 VSCode 与 Anaconda 安装配置全攻略 在当今数字化时代,Python 作为一种功能强大且易于学习的编程语言,被广泛应用于数据科学、人工智能、Web 开发等众多领域。为了顺利开启 Python 编程之旅,搭建一个稳…...
3月报|DolphinScheduler项目进展一览
各位热爱 Apache DolphinScheduler 的小伙伴们,社区3月报来啦!来查看上个月项目的进展吧! 月度Merge Star 感谢以下小伙伴上个月为 Apache DolphinScheduler 所做的精彩贡献(排名不分先后): “ruanwenj…...
Flutter 应用在真机上调试的流程
在真机上调试 Flutter 应用的方法 调试 Flutter 应用有多种方式,可以使用 USB 数据线连接设备到电脑进行调试,也可以通过无线方式进行真机调试。对于 iOS 开发者,使用 appuploader 这样的工具可以更高效地管理开发流程。 1. 有线调试 设备…...
QML TableView:基础用法和自定义样式实现
目录 引言相关阅读工程结构示例一:基础TableView实现代码解析运行效果 示例二:自定义样式TableView代码解析运行效果 主界面运行效果 总结工程下载 引言 TableView作为Qt Quick中的一个核心控件,具有高性能、灵活性强的特点,能够…...