avatar
文章
88
标签
113
分类
4

首页
合集
  • 归档
  • 标签
  • 分类
专栏
  • 开发笔记
  • 日常记录
友链
关于
首页
合集
  • 归档
  • 标签
  • 分类
专栏
  • 开发笔记
  • 日常记录
友链
关于

CYK's Blog

异步任务执行期间状态变了的几个坑
发表于2026-07-01|开发笔记|踩坑•JavaFX•并发•异步
一个数据量比较大的画布应用,后台异步加载、重算数据,算完再渲染到 Canvas。这种结构踩了好几个坑,根子其实都出在同一件事上:异步任务跑的过程中,它依赖的外部状态已经被别的地方改了,任务回来还按旧状态干活,就出错。 下面这几个坑表现完全不一样,但捋到底都是这个原因。 整块空白后台读完数据回来,往像素缓冲区里写的时候,要按”上一段的位置”算偏移。问题出在那个”上一段”——遍历的时候有些段因为被别的段完全包含而跳过了,结果拿”上一个没跳过的段”当基准,基准就错了,偏移算成负数,写缓冲越界,抛 IndexOutOfBoundsException。这个异常在渲染流程里被 catch 住了,程序不崩,但这一块就没写进去,画面上就是一片空白,啥报错都没有。 更隐蔽的是另一个根因:待渲染的段列表是个会被原地 clear() + 重建的 ArrayList。后台线程正迭代它的时候,主线程正好在 clear + add 重建,后台读到的就是个半新半旧的列表,照样算出错误的段。 第一个修法是基准只用”真正产生了段的项”,被跳过的不当参照。第二个是段列表改成不可变快照发布: private volatil ...
做 licence 防破解踩的几个坑
发表于2026-07-01|开发笔记|Java•licence•安全•防破解
给一个 Java 工具做了套 licence,要解决两个现实问题:一份 licence 不被全公司共用、不被改系统时间无限续期。先说清楚一点,客户端 licence 本质是抬高破解成本,不是绝对防得住——私钥不泄露的前提下,能做到”普通用户懒得搞”的程度,真遇上专业逆向一样会破。 licence 本体是一张 JWT,RSA 私钥签发,客户端内嵌公钥验签。下面几个是做的时候要注意的点。 时间回拨JWT 的过期判断(exp)依赖系统时钟,所以最简单的破解就是把系统时间往回调,过期就判不出来了。 办法是本地存一个单调不降的时间记录:每次校验通过,把当前时间写进 ~/.myapp/.lastseen;下次校验前先比一下,now 比 lastseen 早超过一个容差就拒掉: long lastSeen = Long.parseLong(readLastSeen());long now = System.currentTimeMillis();// 留 5 分钟容差吸收 NTP 微调、时区抖动return now >= lastSeen - CLOCK_ROLLBACK_TOLERANCE_ ...
Dewow:把偏到一边的秤归零
发表于2026-07-01|开发笔记|GPR•雷达•信号处理•高通滤波
原始 A-scan 应该围绕零线上下振动,实际却经常整体偏到一边,像秤没归零。Dewow 就是先把秤拨回零。 为什么会偏波形整体偏移主要来自: 发射天线直接窜到接收天线的耦合信号; 接收机电路的直流偏置和缓慢漂移; 地面耦合条件随推车过程缓慢变化; 低频电磁干扰。 这些成分变化很慢,频率集中在零频和极低频,把真实信号的基线顶歪了。 用滑动平均估计漂移有用反射信号围绕天线中心频率快速振动,正半周和负半周大致抵消。取一个足够长的窗口做滑动平均: 快速振动部分一正一负,平均下来接近 0; 缓慢漂移在窗口里几乎是常数,平均后保留下来。 这个滑动平均就是漂移的估计,把它减掉,漂移就去掉了。 公式: $$\hat d[n]=\frac{1}{W}\sum_{k=-W/2}^{W/2}x[n+k], \qquad \hat s[n]=x[n]-\hat d[n]$$ $x$ 是原信号,$\hat d$ 是估计漂移,$\hat s$ 是输出,$W$ 是窗长,取奇数。 写成 FIR 滤波器,所有抽头之和为 0,意味着直流增益正好是 0——这就是去 ...
微信支付接入踩的几个坑
发表于2026-06-24|开发笔记|踩坑•微信支付•支付
前言微信支付的文档其实挺全,但接入的时候总有些”文档写了、你却未必留意”的坑。下面是我自己踩过或者帮人排查过的几条,不绑具体项目,只说通用经验。 平台公钥模式 vs 证书模式,怎么选微信支付回调验签现在主要有两种配置: 证书模式(RSAAutoCertificateConfig):SDK 自动下载并轮换平台证书。 平台公钥模式(RSAPublicKeyNotificationConfig):用一份固定的平台公钥验签。 证书模式省事,但在平台证书切换的那段时间,有可能 SDK 还没更新到新证书,验签就会失败。公钥模式稳定些,缺点是真到了换公钥的时候,得自己手动换文件。 我的选择是:商户号稳定、回调量不大的,用公钥模式,自己可控;商户号活跃、证书换得勤的,用证书模式,但切换那几天盯着点失败率。 回调 body 必须取原始字符串这是最容易踩的坑。微信支付回调的签名是对原始请求体算的,所以接回调时 body 得原封不动拿到,不能让框架先帮你反序列化: @PostMapping("/notify")public ResponseEntity<String> n ...
支付状态同步-异步回调与主动查单兜底
发表于2026-06-24|开发笔记|支付•架构•回调•对账
不能只靠回调支付平台一般是异步回调通知商户:用户付完钱,平台往你的 /notify 地址 POST 一个请求,告诉你”这笔订单付了”。 但回调这东西不能全信。网络抖动、服务器重启、notify-url 改了、DNS 出问题、甚至平台那边延迟,都可能让回调丢掉或者晚到。只靠回调,迟早会遇到”用户钱都付了,你这边还不知道”这种情况。 所以支付状态同步一般做成:异步回调(推)+ 主动查单(拉),两条腿走路。 推和拉各管什么支付平台 商户服务 │ │ │ ① 用户完成支付 │ │ │ │──── POST /notify ────▶│ 推:被动接收支付结果 │ │ │◀── 返回 SUCCESS ──────│ │ │ │ │ │◀── GET /queryOrder ───│ 拉:主动查询 ...
支付回调的幂等设计
发表于2026-06-24|开发笔记|支付•幂等•架构
为什么回调必须幂等支付平台为了让你一定收到通知,回调是会重试的。同一笔订单支付成功,你这边可能收到一次、两次,甚至更多次 /notify。 如果每次回调都老老实实走一遍”更新订单 + 发货 + 开通权益”,轻则重复发货,重则重复扣库存、给用户重复加钱。所以回调这步必须做成幂等——同一笔通知来多少次,结果都一样。这块平时不起眼,但出了事基本都是它。 思路这三样我习惯叠在一起用,单独靠哪一个都不够稳。 状态机:PAID 是个单向终点订单状态尽量简单: PENDING → PAID ↓EXPIRED / CANCELLED PAID 只能从 PENDING 转过来。已经是 PAID 的订单再收到回调,直接返回成功,什么都不做——这是挡重复通知的第一步。 if (order.status == PAID) { return success; // 处理过了,直接 Ack}if (order.status != PENDING) { throw illegalState(); // 过期或已取消的订单,不再接受支付通知} 数据库唯一键 ...
GPR 数据到底长什么样:A-scan、B-scan 与采样定理
发表于2026-06-24|开发笔记|GPR•雷达•信号处理•采样定理
探地雷达往地下打一束高频电磁脉冲,遇到材料变了的地方,一部分反射回来,剩下的继续往下走。仪器只记录两个数:什么时候回来,回来有多强。所有 GPR 数据说到底就是这个。 反射和深度反射强弱看界面两边材料差多少: $$R = \frac{\sqrt{\varepsilon_1}-\sqrt{\varepsilon_2}}{\sqrt{\varepsilon_1}+\sqrt{\varepsilon_2}}$$ 混凝土介电常数大概 6~9,空气接近 1。衬砌背后出现空洞时,两边差得大,反射就强。空洞、脱空能被探到,原因就在这里。 深度从回波时间换算: $$d = \frac{v \cdot t}{2}, \qquad v = \frac{c}{\sqrt{\varepsilon_r}}$$ $t$ 是电磁波下去再上来的双程时间,所以除以 2。光速 $c=0.3,\text{m/ns}$,混凝土里波速大概 $0.10\sim0.12,\text{m/ns}$。回波时间对应深度,回波强弱对应界面差异——这两句话是后面所有算法的基础。 A ...
零线刷新幂等去重 缓存数组逐元素比较
发表于2026-06-17|开发笔记|踩坑•Kotlin•性能优化•幂等
现象零线对齐初始化那阵,发现磁盘被频繁读、初始化很慢。profile 了一下,看到 reloadBuffer 被反复触发了很多次。 原因初始化时有好几个事件源(不同组件的状态变更)都会触发 reloadBuffer——也就是重新从磁盘读雷达数据再刷新。这些事件短时间里密集到达,虽然最后零线的状态其实没变,但每次都老老实实重读一遍磁盘,做了大量重复 IO。 去重要让刷新幂等,说白了就是相同的输入只处理一次。把上一次的 zeroPositions 数组缓存下来,新事件来了先比一比新旧: fun onZeroLineUpdate(newPositions: DoubleArray) { if (newPositions contentEquals lastPositions) return // 没变,跳过 lastPositions = newPositions.copyOf() reloadBuffer()} 为什么不算哈希第一反应可能是算个哈希比一下,快。但哈希会碰撞:两个内容不同的数组哈希恰好一样,就会被当成”没变”漏掉刷新,雷达图就错位了 ...
雷达采样直方图从 O(N×M) 优化到 O(N) 单遍桶计数
发表于2026-06-15|开发笔记|Kotlin•性能优化•算法•直方图
背景雷达图渲染前要统计采样值的分布——算百分位、做增益和对比度映射,这步一般叫”采样直方图”。打开一个多文件的测线时,每打开一个文件都得算一遍。 原来的 O(N×M)最早的做法是”对每个待统计的输出桶,把所有采样点扫一遍,数有多少落进这个桶”。N 个采样点 × M 个桶,复杂度 O(N×M)。单文件几百万采样点的时候,光这一步就把打开速度拖慢一大截,多文件叠在一起更明显。 改成 O(N) 单遍桶计数其实直方图没必要每个桶都扫一遍数据。一趟遍历,把每个采样点直接扔进它对应的桶就行了: fun histogram(samples: IntArray, min: Int, max: Int, bucketCount: Int): IntArray { val buckets = IntArray(bucketCount) val range = (max - min).coerceAtLeast(1) for (v in samples) { val idx = ((v - min).toLong() * bucketCount / ran ...
Kotlin 协程生命周期 SupervisorJob 与 Mutex 超时保护
发表于2026-05-22|开发笔记|Kotlin•协程•并发•生命周期
SupervisorJob默认情况下,协程作用域用的是 Job(),父子关系就像一根绳上的蚂蚱——任意一个子协程抛异常,整个作用域(包括其他正常跑着的兄弟协程)都会被取消。对于”加载多条测线、其中一条失败不该拖累其他”的场景,这就太脆了。 换成 SupervisorJob(),子协程的失败不会往上传播,其他兄弟照常跑: class RadarViewModel { private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)} @PreDestroy协程要是不主动取消,它会一直挂着,引用着 ViewModel / UI,造成内存泄漏,甚至组件都销毁了还跑回来刷新一个已经失效的 UI。把 scope 的取消绑到生命周期上: @PreDestroyfun onDestroy() { scope.cancel() // 取消所有子协程} Mutex 加超时共有 / 复合病害的计算可能短时间里被触发好几次(连续编辑),不加锁的话,两个并 ...
1234…9
avatar
CYK
我是CYK
文章
88
标签
113
分类
4
公告

怎么这么难!
我真服了!

最新文章
oh-my-posh:一个好看的终端提示符怎么装2026-08-05
DOCX Pipeline v1.2.0:Markdown 转 Word,顺便把 LaTeX 公式也塞进去2026-07-22
横向平滑:抹掉 GPR 剖面上的窄条纹2026-07-22
给图像做完增益别再用整张图的百分位定色阶2026-07-15
GPR 时间增益与 AGC:把深部提亮的两条路2026-07-15
分类
  • 学习笔记1 篇
  • 工具笔记1 篇
  • 开发笔记84 篇
  • 生活记录1 篇
标签
Python 基础 命令行 MAVEN 增益 支付 数据结构 JAVA SCRIPT Canvas SQL优化 Nacos RAG docker 属性绑定 JDK25 异步 Spring 解耦 资源 信号处理 ORACLE RocketMQ Redis Java2D 算法 数据库 打包 数据处理 小程序 DOCKER 事件总线 架构 批量更新 SVN 工具 Excel 图像处理 桌面开发 MongoDb file browser
归档
  • 八月 20261 篇
  • 七月 202622 篇
  • 六月 20266 篇
  • 五月 20265 篇
  • 四月 20264 篇
  • 三月 20262 篇
  • 二月 20264 篇
  • 一月 20262 篇
网站资讯
本站访客数 :
本站总访问量 :
©2024 - 2026 By CYK

HEXO Butterfly GitHub
鲁ICP备2024065423号-1

搜索