CountDownLatch翻车后,我建议用CompletableFuture改造下

CompletableFuture使用不当的生产问题记录 1 阅读详情

CompletableFuture改造

我先直接分享一下我是如何使用CompletableFuture的吧

// 下载文件总数,初始化
List<Integer> resultList = new ArrayList<>(1000);
ConcurrentHashMap<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();
IntStream.range(0,1000).forEach(resultList::add);

public List<R> sendAsyncBatch(List<P> list, Executor executor, TaskLoader<R,P> loader) {

    List<R> resultList = new CopyOnWriteArrayList<>();
    if (CollectionUtils.isNotEmpty(list)) {
        Executor finalExecutor = executor;
        // 将任务拆分分成每50个为一个任务
        CollUtil.split(list, 50)
                .forEach(tempList -> {
                    CompletableFuture[] completableFutures = tempList.stream()
                            .map(p -> CompletableFuture.supplyAsync(() -> {
                                try {
                                    return loader.load(p);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                return null;
                            }, finalExecutor)
                                    .handle((result, throwable) -> {
                                        if (Objects.nonNull(throwable)) {
                                            //log.error("async error:{}", throwable.getMessage());
                                        } else if (Objects.nonNull(result)) {
                                            //log.info("async success:{}", result);
                                        } else {
                                            //log.error("async result is null");
                                        }
                                        return result;
                                    }).whenComplete((r, ex) -> {
                                        if (Objects.nonNull(r)) {
                                            resultList.add((R) r);
                                        }
                                    })
                            ).toArray(CompletableFuture[]::new);
                    CompletableFuture.allOf(completableFutures).join();
                    System.out.println(resultList.size());
                });
    }
    return resultList;
}

// 具体业务逻辑实现接口
@FunctionalInterface
public interface TaskLoader<T,P> {

    T load(P p) throws InterruptedException;
}

//  自定义启动器
ExecutorService executorService = BaseThreadPoolExector.queueExecutor(new ArrayBlockingQueue<>(5));
AsyncTask<Integer, Integer> asyncTask = new AsyncTask();

List<Integer> list = asyncTask.sendAsyncBatch(resultList, executorService, new TaskLoadImpl());

我先说一下,为什么要CountDownLatch替换掉

  1. CompletableFuture为我们提供更直观、更优美的API。
  2. 在“多个任务等待完成状态”这个应用场景,在遇到异常的情况下我们不需要去手动的抛异常,以免错误处理细节导致阻塞
  3. CompletableFuture也可以定制执行器

但是他也是有缺点的,我个人感觉他的API有点多,看的时候让人眼花。

短短十几行的代码,看到了很多API supplyAsync、handle、whenComplete、allOf

之后我们还会用到runAsync、 thenApply、thenCompose等等其他的。

什么是CompletableFuture?

异步编程,利用多线程优化性能这个核心方案得以实施的基础

他的目的也很简单,同一个CPU上执行几个松耦合的任务,充分利用CPU核数,实现最大化吞吐量,避免因为阻塞造成等待时间过长;

1. 要区分并发与并行的区别

我们还需要特别的注意这两个概念不能混淆

并发:在一个CPU上串行执行

并行:多个CPU上同时执行任务

2. Future接口

CompletableFuture主要继承了Future接口,但是他比Future接口丰富的很多

// 取消
boolean cancel(boolean mayInterruptIfRunning);

// 判断是否取消
boolean isCancelled();

//是否异步计算是否已经结束
boolean isDone();

// 获取计算结果
V get() throws InterruptedException, ExecutionException;

// 设置最长计算时间,返回计算结果
V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;

可以看到Future接口的局限性,主要是用起来不省事 举个例子:A线程执行完之后通知B线程执行

ExecutorService executorService = BaseThreadPoolExector.calculateExecutor();
Future<String> futureA = executorService.submit(() -> Thread.currentThread().getName());
System.out.println(futureA.get());
if (futureA.isDone()){
    Future<String> futureB = executorService.submit(() -> Thread.currentThread().getName());
    System.out.println(futureB.get());
}
executorService.shutdown();
、

这里我们就需要查询futureA.isDone()结果,然后再去执行B线程的业务

而 CompletableFuture 操作起来就便捷很多了

CompletableFuture<String> completableFuture = CompletableFuture
        .supplyAsync(() -> Thread.currentThread().getName(), executorService)
        .thenApply(s -> Thread.currentThread().getName());
System.out.println(completableFuture.get());

准备执行
计划执行
supplyAsync result pool-1-thread-1, thenApply result main
线程退出
复制代码

supplyAsync执行完成之后,再去执行thenApply

没有繁琐的手工维护线程的工作,给任务分配线程的工作也不需要我们关注;

3. 错误处理细节,避免造成阻塞

CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
new Thread(() ->{
    try {
        int kk = 10/0;
        System.out.println(kk);
    }catch (Exception ex){
        //ex.printStackTrace();
        completableFuture.completeExceptionally(ex);
    }

}).start();
try {
    System.out.println(completableFuture.get());
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

注意到catch里面的completeExceptionally函数了吧,

这个主要的作用就是为了抛出异常,

如果缺少了他,就会造成completableFuture.get()一直处于等待造成阻塞,

与此同时,没有为我们抛出异常信息。

所以CompletableFuture的API优美之处又要体现出来了

CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
    int kk = 10 / 0;
    return kk;
}).handle((result, throwable) -> {
    System.out.println(result);
    System.out.println(throwable.getMessage());
    return result;
}).whenComplete((result ,throwable) -> System.out.println(result));

supplyAsync配合着 handle 和 whenComplete,将异常和结果进行处理.

handle 和 whenComplete的区别

whenComplete
public CompletableFuture<T> whenComplete(
    BiConsumer<? super T, ? super Throwable> action) {
    return uniWhenCompleteStage(null, action);
}
handle
public <U> CompletableFuture<U> handle(
    BiFunction<? super T, Throwable, ? extends U> fn) {
    return uniHandleStage(null, fn);
}

whenComplete是BiConsumer也就是直接消费不返回值,

handle是BiFunction也就是需要返回值

了解API

欲善其功,必先利其器

我们主要从这三种关系下手去了解和使用API 涉及接口

CompletionStage<R> thenApply(fn);   
CompletionStage<R> thenApplyAsync(fn);           
CompletionStage<Void> thenAccept(consumer);      
CompletionStage<Void> thenAcceptAsync(consumer); 
CompletionStage<Void> thenRun(action);           
CompletionStage<Void> thenRunAsync(action);      
CompletionStage<R> thenCompose(fn);              
CompletionStage<R> thenComposeAsync(fn);

thenApply函数里参数入参Function<? super T,? extends U> fn,这个接口里与 CompletionStage 相关的方法是 R apply(T t),这个方法既能接收参数也支持返回值,所以 thenApply函数出参的是CompletionStage<R>。

thenAccept类型函数入参Consumer<? super T> action是一个消费类型的,回参是CompletionStage<Void>所以thenAccept类型函数不会有返回值。

thenRun函数入参Runnable action,回参CompletionStage<Void>,所以既不能接收参数也不支持返回值。

thenCombine函数入参CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn,回参CompletableFuture<V>是支持返回值的,他的作用主要使用BiFunction处理两个阶段的结果

我们只需要注意他的入参、回参和函数后缀就能够区分出他们的不同

1. CompletableFuture中的串行化关系

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() ->{
    //int kk = 10/0;
    return Thread.currentThread().getName() + ":小郭";
},executorService).thenApply(s -> {
    return s + "拿茶叶";
}).thenApply(a ->{
    return a + ",泡茶去";
}).handle((result, ex) ->{
    if (ex != null){
        System.out.println(ex.getMessage());
    }
    return result;
}).whenComplete((r, ex) ->{
    System.out.println(r);
});
task1.join();

执行结果:

准备执行
计划执行
pool-1-thread-1:小郭拿茶叶,泡茶去

可以看到,是按照之上而下的顺序去执行的supplyAsync、thenApply、thenApply 如果第二阶段任务没有拿到第一阶段的结果,他就会等待

2. CompletableFuture中的汇聚AND关系

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() ->{
    int t = new Random().nextInt(30);
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("task1=" + t);
    return t;
});
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() ->{
    int t = new Random().nextInt(30);
    try {
        Thread.sleep(t);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("task2=" + t);
    return t;
});
CompletableFuture<Integer> task3 = task1.thenCombineAsync(task2, Integer::sum);
task3.join();

等待task1和task2执行完成,task再进行处理

执行结果

task1=1
task2=3
4

3. CompletableFuture中的汇聚OR关系

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() ->{
    int t = new Random().nextInt(5);
    try {
        Thread.sleep(t * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("task1=" + t);
    return t;
});
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() ->{
    int t = new Random().nextInt(5);
    try {
        Thread.sleep(t * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("task2=" + t);
    return t;
});
CompletableFuture<Integer> task3 = task1.applyToEither(task2, s ->s);
task3.join();

谁先执行完先输出谁,如果相同时间执行完,则一起数据

执行结果

我快我先来 task2=2
我快我先来 task1=2
2

我快我先来 task2=0
0

实现List任务并行执行的方式

  1. 并行流进行操作
  2. 使用CompletableFuture发起异步请求,最后使用join等待所有异步操作结束

为了更好的发挥出CompletableFuture,需要采用定制的执行器

那这两个如何选择?

  1. 进行计算密集型,并且没有I/O操作,推荐使用Sream并行流,没必要创建更多的线程,线程过多反而是一种浪费
  2. 涉及I/O等待的操作,CompletableFuture的灵活性会更高

现在回过头看一下,我上面的改造方法,是不是就感觉清晰了许多,不足的地方大家提出来

总结

  1. 章我主要是根据大家的建议,使用了Java8的CompletableFuture 来进行了原来的业务功能改造.
  2. 在执行比较耗时的业务操作时候可以使用异步编程来提高性能,加快程序的处理速度
  3. 在处理异常机制的时候,往往是让我们很头痛的,担心线程中出现的异常没有及时捕获,造成程序的阻塞或者其他方面的影响,CompletableFuture 提供了优秀的异常管理机制。
  4. CompletableFuture 还提供了 串行、聚合、优先输出的函数,更贴切业务需求做出最好的选择。
CompleteFuture的介绍和使用 阅读详情

相关推荐

CompleteFuture异步处理和多线程异步处理有什么区别

CompleteFuture是Java SE 8中新增的一个异步处理工具类,它可以将一个异步的操作封装为一个Future对象,并允许你设置一个回调函数在操作完成后执行。而多线程异步处理是通过创建线程来执行并行任务,以达到异步处理的效果。可以看到,使用 CompleteFuture 可以通过 thenAccept() 方法来设置异步操作完成后的回调函数。这个回调函数将在指定的线程池执行,参数是异步操作的返回值,而且不会阻塞主线程的执行。两者的区别在于实现方式不同。

优秀的程序员不应该是CRUD 2968

高并发场景实战: 线程池,countDownLatch,CompletableFuture混合使用

写在前面: 希望大家从一开始就跟着敲, 收获一定是满满的, 末尾会留公众号,想一起努力的小朋友可以一起加入, 由兴趣可一起维护我们共同的公众号。 1:项目搭建 需要引入的maven //提供线程池,TransmittableThreadLocal两个工具类 <dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-threa.

qq_37805943的博客 2808

Java并发编程面试核心原理精讲:从synchronized到AQS

并发编程是Java后端开发的核心技能,也是面试中容易拉开差距的环节。从CPU缓存与内存模型出发,理解可见性、原子性与有序性是掌握并发底层逻辑的基础。JMM定义了线程间共享变量的通信规则,volatile通过内存屏障保证可见性与禁止重排序,而synchronized则借助对象头Mark Word实现锁升级,从偏向锁到重量级锁的演进体现了对竞争场景的深度优化。进一步深入JUC工具包,CAS无锁算法与AQS抽象队列同步器构成了ReentrantLock、Semaphore等同步器的基石。线程池作为生产环境最常用的

weixin_34194087的博客 331

搬砖日记-CountDownLatch和CompletableFuture的使用

搬砖日记-CountDownLatch和CompletableFuture的使用 前言 不知不觉在大厂搬砖快一年了,在这一年里不得不说我学到了很多,特别把之前学到的知识给落地,这给我带来一些满足感和充实感,于是我想着抽空把最近学到的知识给整理整理,既是温习回顾还是一种分享,本篇文章将带领大家了解一下CountDownLatch和CompletableFuture的使用. 正文 CountDownLatch CountDownLatch程序计数器: CountDownLatch用于主线程等待其他子线程任务都

蹊源的奇思妙想的博客 2551

深入AQS:Java并发核心原理与自定义同步器实战

在Java并发编程中,锁和同步器是构建线程安全程序的基础组件。其核心原理在于通过原子操作和队列管理,协调多线程对共享资源的访问,以实现互斥与同步。AQS(AbstractQueuedSynchronizer)作为JUC(Java Util Concurrent)库的基石,采用模板方法模式,将复杂的线程排队、阻塞与唤醒机制封装成通用框架,其价值在于为开发者提供了构建高性能、可扩展同步器(如ReentrantLock、Semaphore)的底层支撑。在高并发场景下,理解AQS的state状态管理、CLH队列变体

weixin_34413103的博客 426

Java八股文面试核心考点梳理:从JVM到Kafka的工程师修炼指南

在Java技术面试中,八股文常被误解为死记硬背,实则是检验知识体系的关键索引。从JVM内存模型与垃圾回收、并发编程的锁升级与AQS原理,到Spring IOC/AOP与循环依赖、MySQL B+树索引,再到Redis缓存异常与Kafka百万并发架构,这些核心考点共同构成大厂工程师的底层能力地图。掌握其原理,不仅能通过面试,更能指导线上性能优化与高并发系统设计。本文结合工程实践,梳理高频考点与高效备考方法,帮助读者将零散知识串联成完整体系。

weixin_32430941的博客 224

CountDownLatch翻车后,我建议大家用CompletableFuture改造

异步编程,利用多线程优化性能这个核心方案得以实施的基础他的目的也很简单,同一个CPU上执行几个松耦合的任务,充分利用CPU核数,实现最大化吞吐量,避免因为阻塞造成等待时间过长;章我主要是根据大家的建议,使用了Java8的CompletableFuture 来进行了原来的业务功能改造.在执行比较耗时的业务操作时候可以使用异步编程来提高性能,加快程序的处理速度。

weixin_62421895的博客 827

2025.06.20【pacbio】|PB甲基化分析结果的统计与可视化介绍

本文介绍了PacBio甲基化数据的统计分析与可视化方法。主要内容包括:1) 分析甲基化位点分布、比例及染色体分布;2) 修饰基序(Motif)的统计与热图展示;3) 全基因组和局部区域测序深度可视化;4) 使用IGV查看单个reads修饰情况。文章提供了R代码示例,涵盖柱状图、分布图、热图等多种可视化形式,并建议了差异甲基化分析等进阶方法,帮助科研人员深入挖掘甲基化数据。

2065

翻车后,大家都建议我用CompletableFuture改造下,改造完真香啊

异步编程,利用多线程优化性能这个核心方案得以实施的基础他的目的也很简单,同一个CPU上执行几个松耦合的任务,充分利用CPU核数,实现最大化吞吐量,避免因为阻塞造成等待时间过长;这篇文章我主要是根据大家的建议,使用了Java8的CompletableFuture 来进行了原来的业务功能改造.在执行比较耗时的业务操作时候可以使用异步编程来提高性能,加快程序的处理速度。

Java_zhujia的博客 742

保姆级教程:用CH34xSerCfg工具修改USB转串口芯片的VID/PID,避免驱动冲突

本文详细介绍了如何使用CH34xSerCfg工具修改USB转串口芯片的VID/PID,解决驱动冲突问题。通过实战案例和配置技巧,帮助开发者高效管理嵌入式设备,避免常见的USB设备识别问题,提升开发效率。

weixin_30924239的博客 224

Centos7配置阿里云镜像源的教程

查看你的Centos版本,版本过低会导致安装失败,验证网络是否可以连接阿里云镜像,使用阿里云是需要网络的。# wget命令下载: wget [options] [url]# curl命令下载: curl [options] [url]我上面这个图片由于电脑问题是还没有加载完的。删除原来或者之前的yun源。

lyhshs的博客 2259

翻车后!大家都建议我用CompletableFuture改造下,改造完真香啊

异步编程,利用多线程优化性能这个核心方案得以实施的基础他的目的也很简单,同一个CPU上执行几个松耦合的任务,充分利用CPU核数,实现最大化吞吐量,避免因为阻塞造成等待时间过长;这篇文章我主要是根据大家的建议,使用了Java8的CompletableFuture 来进行了原来的业务功能改造.在执行比较耗时的业务操作时候可以使用异步编程来提高性能,加快程序的处理速度。

z1ztai的博客 638

iStore增强插件 如何重塑家庭网络与存储体验

本文深入解析了iStore增强插件如何重塑家庭数字生活体验。它通过集成智能流控、一键式文件共享、媒体服务器及智能家居网关等功能,将复杂的网络配置、存储管理与设备协同简化为图形化操作,有效解决了家庭网络卡顿、数据割裂与使用门槛高等核心痛点,让普通用户也能轻松打造高效、稳定、安全的家庭数字中枢。

prometheus9mon的博客 646

从面试官视角拆解多线程:为什么这些“八股文”能筛掉90%的候选人?

本文从面试官视角深入剖析多线程面试题的核心考察点,揭示为何这些题目能筛掉90%的候选人。文章详细解析了线程池调优、锁优化、并发容器选择等关键技术,并提供了实战案例和性能优化建议,帮助开发者全面提升多线程编程能力。

weixin_33910759的博客 342

基础的pdf病毒木马

基础的pdf病毒木马 环境: 攻击机:Kali 目标操作系统:Windows 10或Windows 7 (关闭防火墙和安全软件) 目标软件:Adobe Reader 8.1.2 msf框架搜索:adobe-pdf 1.打开msfconsole 2.搜索 adobe_pdf模块 3.加载攻击模块并设置payload 4.运行生成pdf 5.将pdf拖入到win10 6.打开msf,加...

小小猪的博客 4621

AI大模型探索之路-训练篇3:大语言模型全景解读

大规模语言模型(Large Language Models,LLM),也称大语言模型或大型语言模型,是一种由包含数百亿以上参数的深度神经网络构建的语言模型,通常使用自监督学习方法通过大量无标注文本进行训练。

寻道AI,探索AI无限可能! 6270

顺序工作流异步执行:CompletableFuture异常传播机制详解

异步编程是提升系统吞吐能力的关键技术,而完整任务链的编排离不开对工作流执行顺序的精确控制。Java中的CompletableFuture为异步任务提供了强大的编排能力,支持串行依赖、并行聚合以及异常恢复等核心操作。但在实际工程中,开发者常常遇到后续异步任务因上游异常而中断执行的困境,这源于框架自身的失败快速传播机制,而非随机故障。理解异常如何在CompletableFuture链式调用中流转,掌握thenApply、thenCompose、exceptionally等方法的适用边界,是构建健壮异步任务流的基

weixin_34221654的博客 358

【用unity实现100个游戏之1】制作类元气骑士、挺进地牢——俯视角射击游戏多种射击效果(一)(附源码)

俯视角射击游戏)是一类以俯视视角进行游戏展示的射击游戏。在这种游戏中,玩家控制着一个角色或载具,从俯视的角度上方观察游戏世界,并与敌人进行战斗。这种视角使玩家能够有更好的全局观察和策略性,同时也强调快速反应和精确射击。视角:俯视角度可以是固定的,也可以随着玩家角色的移动而变化,但都允许玩家以全局视角观察整个战场,有利于制定战略和规划行动。射击:玩家通常需要使用各种武器来与敌人进行战斗,包括枪械、爆炸物等。射击动作依赖于玩家的反应速度和准确性。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 7828

别再背 API 了!Java 并发编程的正确学习路线

学并发不是背 API,而是理解三大核心问题:原子性、可见性、有序性。本文从问题出发,用代码示例串起 volatile、synchronized、CAS、AQS、线程协作、CompletableFuture、线程池、死锁排查的完整学习路线。

qq_34219119的博客 203

RK3588开发笔记-麦克风阵列多pdm通道合并成一个声卡

在音频设备的开发中,特别是在多通道音频数据处理场景中,如何将多个PDM(Pulse Density Modulation)通道整合成一个声卡设备,是一个非常具有挑战性的问题。RK3588芯片作为一款性能强大的平台,提供了对多个音频通道的支持。本文将介绍如何在RK3588上将多个PDM通道合并成一个麦克风阵列声卡,从而在Linux系统下统一管理和使用,提高多通道音频的同步性。在本文中我们主要介绍使用2通道回采+4通道mic声音采集构成一个6通道声卡,加以回声消除实现一个多麦克风阵列。

flypig has a dream! 1924

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Java后端简历优化指南:金九银十面试通关要点

在技术人才招聘中,简历筛选是决定候选人能否进入面试的关键环节。招聘方通常会通过关键词匹配、技术栈契合度、项目经验深度来快速判断候选人的能力。Java后端开发者若能在简历中精准呈现Spring Boot、Redis、消息队列、高并发等核心技术能力,并用量化数据突出项目贡献,就能显著提升简历通过率。结合当前企业对AI大模型应用集成的关注,具备调用大模型接口、RAG知识库落地经验的候选人更具竞争优势。本文从HR筛选视角出发,分析Java后端简历石沉大海的常见原因,并给出项目描述、场景题准备、AI能力呈现等具体策略

weixin_29895109的博客 372

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java多线程面试题梳理:从并发原理到线程池实战的3天备考主线

在Java开发岗位的面试中,多线程与并发编程几乎是必考模块。很多候选人能背诵synchronized与volatile的关键字特性,却难以讲清锁升级、内存屏障与线程池参数背后的设计逻辑。理解并发编程,首先要从Java内存模型(JMM)与并发三大特性——原子性、可见性、有序性入手,这是分析一切线程安全问题的理论基础。在此基础上,synchronized的锁升级机制与volatile禁止指令重排序的原理,构成了JVM层面解决并发问题的核心手段。进一步地,JUC工具包中的ReentrantLock、CountDo

weixin_32175665的博客 242

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Java多线程面试核心考点详解:线程池、锁与JMM实战

多线程编程是Java后端开发的核心技能,线程池作为任务调度的关键机制,能有效管理线程生命周期。其底层依赖JMM(Java内存模型)定义共享变量的可见性规则,而synchronized与volatile则分别通过锁和内存屏障保障线程安全。掌握这些原理不仅可以避免死锁、数据竞争等隐患,还能提升系统的并发吞吐能力。在实际工程中,无论是批量数据导入还是高并发接口设计,合理配置线程池参数、选择锁策略及处理ThreadLocal内存泄漏都至关重要。围绕这些高频考点,系统梳理线程基础、锁升级、JUC工具及手写代码模板,助

weixin_34199764的博客 223

Java面试新趋势:从八股文到场景化深度考察的实战应对策略

在Java技术领域,面试考察正从传统的知识点背诵转向对技术原理深度理解和复杂场景解决能力的评估。理解技术原理是掌握Java并发编程、JVM性能调优、MySQL索引优化等核心概念的基础。这些原理知识能够帮助开发者在高并发、分布式系统等实际应用场景中,设计出高性能、高可用的解决方案,从而体现其技术价值。例如,深入理解JVM内存模型和垃圾回收机制,对于诊断线上OOM问题和进行系统调优至关重要;掌握MySQL的B+树索引原理和事务隔离级别,是设计千万级数据表架构和保证数据一致性的前提。当前,面试官更关注候选人能否将

weixin_34210740的博客 350

LlamaIndex Workflow 7大模式实战:分支/循环/并发/嵌套/流式/子类化/可视化,每个模式踩了1个坑

事件命名规范XXXEvent,见名知意状态隔离:多用户使用,避免全局状态污染异常处理:步骤内try/except,统一错误事件超时控制防止步骤卡死流式优先:用户交互使用测试:单元测试每个步骤,模拟事件输入日志:开启工作流日志,排查问题。

专注 Java / Python 开发,AI 大模型应用学习,持续输出源码教程,实战项目案例,学习笔记,拒绝空话,只写能直接跑的代码与可落地方案,关注我,一起少走弯路。 591
上一篇: RocketMQ中的消息存储结构及删除机制
下一篇: 字典服务的设计与管理
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值