并发 01 · 开篇-并发为什么难
这是「Java 并发编程」系列的第一篇。开个头先问一个看着简单、却几乎每个后端都栽过跟头的问题两个线程同时给一个int变量各加一万次最后结果一定是两万吗答案是——不一定甚至大概率不是。一段这么朴素的代码为什么会算错把这件事从根儿上讲明白基本就摸到了并发编程的门槛。并发难不是难在 API 记不住。Thread、synchronized、Lock、线程池名词就那么几十个背一背都会。真正难的地方在于并发世界里很多你以为理所当然的常识是不成立的——代码不一定按你写的顺序执行一个线程改了的值另一个线程不一定看得见一行count其实是三步操作、随时可能被别人插队。这些反直觉的现象来自 CPU 多核、缓存、编译器优化层层叠叠的底层机制。不理解这些机制写并发就是在拜运气理解了才知道每个锁、每个volatile到底在防什么。这篇作为全系列的地基不急着讲任何具体工具而是先把为什么并发这么难这件事讲透。文章按这条线索展开先搞清楚我们为什么非要用并发、进程和线程到底是什么、上下文切换贵在哪再把并发世界的三个幽灵——可见性、原子性、有序性——用转账和秒杀的例子逐个现形接着完整走一遍一个线程从生到死的状态流转以及怎么优雅地叫停它最后给出整个 14 篇系列的全景地图告诉你这一路要拆解些什么。目录我们为什么非要并发进程、线程与上下文切换三个幽灵可见性、原子性、有序性线程的一生六种状态如何流转中断怎么优雅地叫停一个线程全景地图这个系列要拆解什么一、我们为什么非要并发先讲动机——不然一上来就讲锁会觉得这些麻烦是凭空冒出来的。并发的所有复杂度其实都是为了换两样东西榨干多核 CPU和别让 CPU 干等。第一个动机摩尔定律换挡了。二十年前 CPU 靠不断提主频变快程序员什么都不用管代码明年就自动跑得更快——这叫免费的午餐。但主频卡在几个 GHz 上不去之后功耗和发热顶不住了芯片厂商改走另一条路不提频率改堆核心。今天一台普通服务器动辄几十个核。问题是一段单线程的代码无论多少个核它永远只用得上其中一个——其余的核在旁边闲着。想把机器的算力吃满就只能把任务拆开、让多个线程分到不同核上同时跑。免费的午餐没了想要性能得自己动手做并发这顿饭。第二个动机让 CPU 别干等。后端服务干的活很多时候不是在算而是在等——等数据库返回、等下游 RPC、等磁盘、等网络。一次数据库查询可能要几毫秒对 CPU 来说这几毫秒足够执行几百万条指令了。如果一个线程发起查询后就傻等这段时间 CPU 完全被浪费。用多线程就能让等 A 的数据库和算 B 的逻辑重叠起来等待的时间被别的活填满吞吐量整个上一个台阶。这里要澄清一对常被混用的词并发Concurrency不等于并行Parallelism。并行是真的同时4 个核同一时刻真的有 4 个线程在各自的核上跑。它要求硬件上有多个执行单元。并发是看起来同时哪怕只有 1 个核操作系统靠飞快地在多个线程之间切换这个线程跑一小会、切走、那个线程跑一小会让你感觉它们在一起推进。单核也能并发但单核不可能并行。一个经典类比并发是一个咖啡师在两台机器间来回照看、交替出品一个人应付多单并行是两个咖啡师各站一台机器同时出品多人多单。我们写的并发代码最终能不能并行起来跑满多核要看运行时有几个核、操作系统怎么调度。并发是我们写代码的方式并行是运行时可能获得的效果。这篇之后统一用并发这个词讲的是编程模型。二、进程、线程与上下文切换要理解并发的代价得先分清进程和线程这两个操作系统概念。进程是资源分配的基本单位线程是 CPU 调度的基本单位。这句话是重点拆开说你启动一个 Java 程序操作系统就创建一个进程给它分配一整套独立的资源——最重要的是一块独立的内存地址空间。进程 A 和进程 B 的内存互相隔离A 崩了不会带崩 B但也正因为隔离进程间通信IPC很麻烦得靠管道、共享内存、socket 这些专门机制。一个进程里可以有多个线程。线程是真正被 CPU 拿去执行的单位——操作系统调度的是线程不是进程。同一个进程里的所有线程共享这个进程的内存地址空间同一个堆、同一批全局变量、同一份打开的文件句柄。看到这里并发问题的根源其实已经浮出水面了线程之间共享内存。多个线程能直接读写同一块内存通信方便、切换轻量这是线程相对进程最大的优势但同一块内存谁都能改这件事恰恰就是数据竞争、可见性、原子性一切麻烦的策源地。并发的便利和并发的危险是同一个硬币的两面。对照 JVM 内存模型同一进程内线程私有的是各自的虚拟机栈、程序计数器局部变量放这里天然不共享、天然安全线程共享的是堆和方法区对象实例放堆里这才是竞争发生的地方。所以并发问题几乎总是围着堆里的共享对象打转。这块内存划分在 JVM 系列里详细讲过这里只需记住这条分界线。上下文切换并发不是免费的。前面说单核靠快速切换实现并发这个切换本身有成本。CPU 任一时刻只能跑一个线程当操作系统决定把 CPU 从线程 A 交给线程 B 时要做一整套动作把线程 A 当前的现场——CPU 寄存器的值、程序计数器指到哪了——保存起来存到 A 的内核栈 / TCB 里不然下次 A 回来就不知道自己执行到哪了把线程 B 上次保存的现场恢复到 CPU 寄存器里如果 A 和 B 属于不同进程还要切换内存地址空间切页表这会导致TLB、CPU 缓存大面积失效代价更大。这一套下来单次上下文切换的直接开销通常在微秒级听着不多但它有两个隐蔽的坑一是频率——如果线程切换太频繁比如锁竞争激烈、线程数远超核数CPU 大量时间耗在搬现场而不是干活上这叫**“上下文切换风暴”二是缓存失效**的间接成本——切换后新线程要的数据不在 CPU 缓存里得重新从内存捞这部分开销比那几微秒更隐蔽也更致命。这就解释了一个常见的反直觉现象线程不是开得越多越快。线程数一旦远超 CPU 核数多出来的线程并不能真的并行反而增加了调度和切换的负担性能不升反降。后面第 8 篇讲线程池参数怎么定本质上就是在回答到底该开多少线程这个问题——而它的地基就是这里的上下文切换成本。怎么观察上下文切换Linux 上vmstat 1输出里的cs列就是每秒上下文切换次数pidstat -w -p pid 1能看某个进程的切换频率还能区分自愿切换cswch/s线程主动等 IO / 锁而让出和非自愿切换nvcswch/s时间片用完被抢占。非自愿切换偏高往往意味着线程数过多在抢 CPU。三、三个幽灵可见性、原子性、有序性现在进入并发最核心的部分。开篇那个两个线程各加一万、结果却不到两万的怪事背后其实站着三个幽灵。几乎所有并发 bug都能归到这三个问题里的一个或几个。后面整个系列的锁、volatile、CAS、JMM全是在对付它们。3.1 原子性一行 count 其实是三步先看那段代码privateintcount0;publicvoidincrement(){count;// ← 看起来是一步其实是三步}count在 Java 源码里是一行但编译成字节码 / 机器指令后是三个独立的步骤1. read 从内存把 count 的值读到 CPU 寄存器 比如读到 100 2. modify在寄存器里把它加 1 算出 101 3. write 把 101 写回内存原子性指的就是一个操作要么全做完、要么全不做中间不能被打断。而count这三步之间是可以被线程切换插进来的。设想两个线程同时执行线程 Aread count(100) ─────────────────→ modify(101) → write(101) 线程 B read count(100) → modify(101) → write(101) B 读的时候 A 还没写回读到的也是 100 最终 count 101 ← 两次自增却只涨了 1丢了一次更新两个线程各读到 100、各算出 101、各写回 101本该是 102 的结果变成了 101。这就是那消失的一次自增。放到我们贯穿全系列的秒杀扣库存场景里这个 bug 就是超卖// 库存 1两个请求同时进来抢最后一件if(stock0){// 两个线程都读到 stock1都判断通过stock--;// 都执行减一 → stock 变成 -1卖出了两件}stock--不是原子的if 判断 扣减这个组合更不是原子的。库存只有 1 件却有两个线程都通过了stock 0的检查——超卖就这么发生了。解决原子性靠的是第 3 篇的synchronized、第 4 篇的 CAS、第 5 篇的锁这是并发工具的主线。3.2 可见性你改了我却没看见第二个幽灵更隐蔽。看这段关不掉的循环privatebooleanrunningtrue;// 没加任何修饰publicvoidrun(){while(running){// 线程 A 在这里空转// do work...}}publicvoidstop(){runningfalse;// 线程 B 把开关关掉}直觉上线程 B 把running改成false线程 A 的循环下一圈就该退出。但实际运行线程 A 很可能永远停不下来。原因藏在硬件里。现代 CPU 每个核都有自己的高速缓存L1/L2比主内存快上百倍。线程 A 在某个核上跑为了快它会把running从主内存读进自己核的缓存之后循环每一圈都只看缓存里的副本。线程 B 在另一个核上把running改成false但这个新值可能只写到了B 那个核的缓存里还没同步回主内存、更没通知 A 去刷新——于是A 的缓存里running还是true它压根不知道有人改过。可见性问题就是一个线程对共享变量的修改另一个线程不能及时看到。它的根源是每个核有自己的缓存这个硬件事实。volatile关键字第 3 篇就是专门治它的——被volatile修饰的变量写了立刻刷回主内存、读时强制从主内存拿保证大家看到的是同一个最新值。3.3 有序性代码不一定按你写的顺序跑第三个幽灵最反直觉你写的代码真正执行时顺序可能被打乱。为了让 CPU 流水线更满、让内存访问更高效编译器和 CPU 都会对指令做重排序——只要在单线程看来最终结果不变它就有权调整指令的实际执行顺序这条底线叫as-if-serial。在单线程里这没有任何问题你永远察觉不到。但到了多线程重排序就可能造出诡异的中间状态。最经典的例子是双重检查锁定的单例instancenewSingleton();// 这一行其实是三步new一个对象底层是① 分配内存 → ② 调用构造器初始化 → ③ 把instance指向这块内存。②和③如果被重排成 ①→③→②那么在③执行完、②还没执行时另一个线程恰好看到instance ! null就会拿到一个**分配了内存但还没初始化完的半成品对象**一用就出错。有序性问题就是重排序在多线程下暴露出的破坏性。解决它靠的是volatile禁止重排序、synchronized保证临界区串行。而到底哪些重排序被允许、哪些被禁止这套规则就是第 2 篇要讲的 **Java 内存模型JMM**和happens-before原则——它是整个并发大厦的理论地基。把三个幽灵并排放一起它们的区别就清楚了幽灵一句话根源主要克星原子性操作做到一半被插队一条语句对应多条指令、可被中断synchronized、Lock、CAS可见性改了别人看不见每个 CPU 核有独立缓存volatile、synchronized有序性执行顺序被打乱编译器与 CPU 指令重排序volatile、synchronized、happens-before记住这张表往后每学一个并发工具都可以问一句——它到底在解决这三个里的哪几个这是贯穿全系列的一把钥匙。四、线程的一生六种状态如何流转讲完为什么难回到最具体的载体——线程本身。在 Java 里一个线程从生到死会经历几种状态这是高频面试题答案有明确出处java.lang.Thread.State这个枚举清清楚楚定义了六种状态不多不少。状态含义NEW线程对象已创建new Thread()但还没调用start()RUNNABLE可运行包括正在 CPU 上跑和就绪、等着被调度两种情况BLOCKED阻塞在等一把synchronized锁拿不到进不了临界区WAITING无限期等待主动等别人来唤醒不设超时TIMED_WAITING限时等待等待带超时时间到自动醒TERMINATED终止run()执行完毕或抛异常退出这里有几个特别容易踩的坑恰恰是面试爱抠的点坑一Java 没有单独的运行中状态。操作系统层面线程有就绪Ready排队等 CPU和运行Running正占着 CPU之分。但Java 把这两者合并成了一个RUNNABLE。所以一个 Java 线程显示为RUNNABLE它可能正在飞速执行也可能只是排在就绪队列里等 CPU 翻牌子——JVM 不区分因为这层调度是操作系统的事JVM 管不着也没必要管。坑二BLOCKED只跟synchronized有关。一个线程抢不到synchronized锁时进BLOCKED。但如果它是在等ReentrantLock也就是LockSupport.park()状态却是WAITING或TIMED_WAITING不是BLOCKED。这是synchronized和Lock在底层实现上就不同的一个外显——记住BLOCKED是synchronized专属排查线程 dump 时不会看错。坑三WAITING和TIMED_WAITING只差一个超时参数。同样是等待调用不带超时的方法进WAITING调用带超时的进TIMED_WAITINGobj.wait();// WAITING ↔ obj.wait(1000); TIMED_WAITINGlock.lock();/park();// WAITING ↔ tryLock(1,SECONDS); TIMED_WAITINGthread.join();// WAITING ↔ thread.join(1000); TIMED_WAITING// Thread.sleep(1000); TIMED_WAITING注意一个细节Thread.sleep()只有带时长的版本所以它永远是TIMED_WAITING而且sleep睡觉时不释放锁这跟wait会释放锁形成经典对比第 3 篇细讲。状态之间怎么流转画成一张图最清楚——start()让线程从NEW进入RUNNABLE抢锁失败掉进BLOCKEDwait/park掉进WAITING被唤醒或超时回到RUNNABLE最后run()跑完走向TERMINATED顺带说说创建线程的方式。常被问创建线程有几种方法本质上只有一种——new Thread()再start()其余都是给线程塞任务的不同姿势继承Thread、重写run()最原始但 Java 单继承占了继承名额不推荐。实现Runnable、传给Thread把任务和线程解耦推荐。run()没有返回值、不能抛受检异常。实现CallableFutureTask任务能返回结果、能抛异常配合Future拿结果。第 13 篇异步编排的起点。线程池ExecutorService生产环境的标准答案。手动new Thread()在实际项目里是要被 code review 拦下来的——线程不复用、数量不可控正确做法是交给线程池统一管理第 8 篇。一句话收口面试答创建线程的方式别只背四种写法要点破底层都是 Thread区别在任务怎么给、结果要不要再补一句生产一律用线程池这才是有理解的回答。再补一个容易被问、又容易答漏的点用户线程与守护线程。线程分两种——用户线程User Thread和守护线程Daemon Thread通过thread.setDaemon(true)设置必须在start()之前设否则抛异常。它俩唯一的区别是决定 JVM 什么时候退出JVM 会等所有用户线程都结束才退出但完全不管守护线程死没死。只要还有一个用户线程在跑JVM 就不退而当最后一个用户线程结束时哪怕守护线程还在忙JVM 也会直接退出、把守护线程一并带走。一个类比用户线程是正式员工守护线程是后勤保洁——公司JVM只要还有一个正式员工在上班就不关门但一旦正式员工全下班了保洁不管扫到哪都得立刻走人。最典型的守护线程就是GC 线程它默默在后台回收内存但绝不会因为它还在工作就阻止程序退出。主线程main是用户线程所以我们写的程序默认会等它跑完。这里有个实践红线守护线程里不要放必须善后的逻辑比如写文件、刷缓冲区、释放外部资源——因为它可能在任意时刻被 JVM 无情掐断来不及收尾数据就丢了。五、中断怎么优雅地叫停一个线程线程能启动也得能停下。但怎么停一个线程是并发里一个被严重低估的难点。先说结论Thread有个stop()方法能强行杀死线程但它早就被废弃、绝对不能用。因为它会让线程在任意位置戛然而止——可能正改到共享数据的一半、锁还没释放直接留下一堆残缺状态和死锁。强行掐断从来不是好办法。Java 的正确思路是协作式中断你没法强制别人停下只能礼貌地打个招呼告诉那个线程该收尾了至于什么时候真正停、怎么收尾由那个线程自己决定。这套机制围绕一个中断标志位展开三个方法要分清thread.interrupt();// 请求中断把目标线程的中断标志位置为 truethread.isInterrupted();// 查询读标志位不清除Thread.interrupted();// 查询并清除读完把标志位复位成 false静态方法作用于当前线程正确的响应姿势是被中断的线程在自己的循环里主动检查这个标志位决定何时退出publicvoidrun(){// 用中断标志位作为循环条件而不是自定义的 booleanwhile(!Thread.currentThread().isInterrupted()){doWork();}// 跳出循环后做清理释放资源、回滚状态……cleanup();}还有个关键细节当线程正卡在sleep()、wait()、join()这些阻塞方法里时别的线程对它interrupt()会让阻塞方法立刻抛出InterruptedException提前返回——但同时会把中断标志位清掉复位成 false。这就带来一个经典陷阱try{Thread.sleep(1000);}catch(InterruptedExceptione){// ✗ 坑这里 catch 住却什么都不做中断信号就被吃掉了// 上层再也感知不到有人请求过中断线程可能继续跑下去}正确处理是要么继续把异常往上抛要么手动把中断标志位补回去别让中断信号凭空消失try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();// ✓ 重新设置中断标志把信号传下去// 然后再决定是退出还是收尾}为什么讲开篇要专门花一节讲中断因为它体现了并发编程一个贯穿始终的哲学你无法命令另一个线程只能与它协作。你不能强行改它的执行、不能强行停它能做的只是设置一个共享的信号等它在合适的时机自己来看、自己来响应。理解了这一点后面学wait/notify、学Condition、学线程池的优雅关闭shutdown就是对池里线程逐个interrupt都会顺很多——它们全是协作这两个字的不同展开。六、全景地图这个系列要拆解什么到这儿并发为什么难讲清楚了为榨干多核和不让 CPU 干等我们用多线程多线程共享内存带来便利也带来原子性、可见性、有序性三个幽灵线程有自己的生命周期而我们只能以协作的方式驾驭它。接下来的 13 篇就是沿着如何驯服这三个幽灵这条主线一层层往下拆。先给你整张地图让你知道每一篇站在什么位置地基02JMM 内存模型——把三个幽灵背后的规则happens-before、重排序、内存屏障用一套模型讲透这是所有并发工具的理论根。两把基础锁03-06volatile与synchronized含锁升级→ CAS 与原子类 → AQS 原理ReentrantLock的骨架→ Lock 家族。这四篇是怎么保证原子性和可见性的核心武器库。写对并发07死锁怎么产生和排查、线程安全到底有哪几种策略、不可变对象为什么天生安全。管理线程08线程池原理与调优——生产环境几乎所有并发任务的入口回答到底开多少线程。并发容器与队列09-10ConcurrentHashMap的演进、阻塞队列与生产者-消费者模型。协作工具11-12CountDownLatch/CyclicBarrier/Semaphore等同步工具、ThreadLocal与它的内存泄漏坑。异步与未来13-14CompletableFuture与 Fork/Join 的异步编排最后落到Loom 虚拟线程——JDK 21 带来的这场变革可能会重写我们对该开多少线程的全部认知用它给整个系列收尾。版本提示本系列以 JDK 8 为主线涉及版本差异会随篇标注如偏向锁在 JDK 15 起默认禁用、JEP 374。而虚拟线程Virtual Threads在 JDK 21 转正JEP 444是这几年并发领域最大的一次变化放在收官篇专门讲。读的时候不用切 JDK跟着主线走差异点我会明确提示。并发难难在它挑战直觉代码不按顺序跑、改了的值别人看不见、一行自增能被插队。但这些反常背后是多核、缓存、重排序这些非常讲道理的底层机制——一旦你把机制看清并发就从玄学变成了可以推理的工程。这就是这个系列想带你抵达的地方。这一篇你只要带走三样东西就够了并发的动机榨干多核 不让 CPU 干等、三个幽灵原子性 / 可见性 / 有序性以及每个工具都在治其中哪几个这把钥匙、协作式的线程观你无法命令线程只能与它协作。下一篇我们钻进最底层——Java 内存模型JMM看看 Java 到底用什么规则把这三个幽灵关进笼子里。

相关新闻

设计模式 23 · 收尾总纲:把二十三式串成一张地图

设计模式 23 · 收尾总纲:把二十三式串成一张地图

到这里,「设计模式拆解」系列的正文就要收尾了。从第 1 篇的七大设计原则出发,我们一路走过了创建型 5 个、结构型 7 个、行为型 11 个,共二十三个 GoF 模式(其中冷门的三个合并在一篇讲)。这最后一篇不引入任何新模式,而是做四件事:把散落的模式盘进你天天用的源码里、集中辨析…

2026/8/14 0:38:41 阅读更多 →
中山网站建设骏域:用真诚与专业打造属于您的数字化名片

中山网站建设骏域:用真诚与专业打造属于您的数字化名片

在这个互联网普及率极高,几乎人人都在用手机刷视频、看资讯、逛电商的时代,对于一家企业或者说一个创业者来说,拥有一张漂亮的“数字名片”已经不再是可选项,而是必选项。想象一下,当您的潜在客户在搜索引擎里输入“中山某类产品”或者“中山某项服务”时,如果搜索结果显…

2026/8/14 0:38:41 阅读更多 →
孤能子视角:空间论——选择的差异:观察符切割关系场的显影面展开

孤能子视角:空间论——选择的差异:观察符切割关系场的显影面展开

(在以下的与AI互动中,在EIS理论约束下,DeepSeek叫信兄,Kim叫酷兄,我呢叫水兄。姑且当科幻小说看) (已由信兄整理成文)孤能子视角:空间论 ——选择的差异:观察符切割关系场的显影面展开 EIS理论库认识论分册…

2026/8/14 0:37:40 阅读更多 →

最新新闻

保定满城网站建设:从草根到高端的进阶指南与避坑全攻略

保定满城网站建设:从草根到高端的进阶指南与避坑全攻略

咱们今天不整那些虚头巴脑的学术理论,就坐在保定满城这片热土上,掏心窝子聊聊“保定满城网站建设”这码事儿。很多老板、创业者,包括一些刚起步的个体户,提起建网站,脑子里蹦出来的第一个词往往是“贵”,第二个词是“怕麻烦”。好像网站这东西,是天上的彩虹,看得见摸不…

2026/8/14 13:01:36 阅读更多 →
NID(Network Identification by Deconvolution)反卷积算法数学推导fff

NID(Network Identification by Deconvolution)反卷积算法数学推导fff

NID(Network Identification by Deconvolution)反卷积算法数学推导 NID 方法由 V. Szkely 等提出,是西门子 T3STER 系统提取时间常数谱 R(τ)(或 R(z))的核心算法。它将热阻抗曲线 Zth(t) 通过数值反卷积转化为连续的…

2026/8/14 13:01:36 阅读更多 →
计算机毕业设计之在线心理咨询预约平台

计算机毕业设计之在线心理咨询预约平台

在当今快节奏、高压力的社会环境中,心理健康问题日益凸显,成为影响人们生活质量和工作效率的重要因素。随着公众对心理健康重视程度的提升,对专业心理咨询服务的渴求也愈发强烈。然而,传统心理咨询模式受限于时间、空间及资源分配…

2026/8/14 13:01:36 阅读更多 →
book118 文档下载器怎么用?一个文档编号就能把预览文档变成 PDF

book118 文档下载器怎么用?一个文档编号就能把预览文档变成 PDF

book118 文档下载器怎么用?一个文档编号就能把预览文档变成 PDF 【免费下载链接】book118-downloader 基于java的book118文档下载器 项目地址: https://gitcode.com/gh_mirrors/bo/book118-downloader 深夜赶方案,你在 book118 上翻到一篇正合适的…

2026/8/14 13:01:36 阅读更多 →
【愚公系列】《Android应用案例开发大全》015-LBS类应用掌上杭州(开发前的准备工作)

【愚公系列】《Android应用案例开发大全》015-LBS类应用掌上杭州(开发前的准备工作)

💎【行业认证权威头衔】 ✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家 ✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主 ✔ 技术生态共建先锋&am…

2026/8/14 13:01:36 阅读更多 →
(二十一)人工智能应用--深度学习原理与实战--NLTK自然语言处理工具库常用功能详解

(二十一)人工智能应用--深度学习原理与实战--NLTK自然语言处理工具库常用功能详解

自然语言处理(Natural Language Processing, NLP)是人工智能领域除了计算机视觉以外的另一个重要分支。它处理的对象是人类的自然语言,如中文、英文等。 数据预处理是建立机器学习模型之前至关重要的环节,它直接决定了模型的质量。在NLP领域中,语料的预处理尤为关键。 N…

2026/8/14 13:00:35 阅读更多 →

日新闻

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

在这个流量为王、视觉至上的互联网时代,对于临沂乃至整个山东乃至全国的传统中小企业来说,拥有一张精美的“数字名片”早已不再是可选项,而是生存的必答题。每当夜幕降临,沂河两岸灯火辉煌,物流之都的喧嚣逐渐沉淀为对未来的思考。我们常常听到老板们在茶余饭后探讨:为什…

2026/8/14 0:00:26 阅读更多 →
Flutter与OpenHarmony实现剧本杀组队表单开发实战

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:26 阅读更多 →
大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

在这个数字化浪潮席卷全球的今天,企业想要在激烈的市场竞争中站稳脚跟,拥有一张好看的“数字名片”已经远远不够了。很多老板在刚开始接触互联网业务时,都有一个共同的困惑:为什么我花了钱建的网站,就像是在真空中自嗨?访客进来转了两圈就跑了,线索石沉大海,甚至连客服…

2026/8/14 0:01:27 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/13 10:41:50 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/13 10:41:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/13 10:41:49 阅读更多 →