并发编程使用场景

文章介绍了CountDownLatch用于线程同步,例如在数据批量导入场景中控制线程执行顺序,防止内存溢出。Semaphore则用于限制并发访问的线程数量,优化性能。此外,文章还探讨了ThreadLocal在实现线程间资源隔离和避免线程安全问题上的作用,以及其可能导致的内存泄漏问题,并强调了主动释放资源的重要性。
摘要由CSDN通过智能技术生成

线程池使用场景CountDownLatch

在这里插入图片描述
CountDownLatch
CountDownlatch (闭锁/倒计时锁)用来进行线程同步协作,等待所有线程完成倒计时(一个或者多个线程,等待其他多个线程完成某件事情之后才能执行)
其中构造参数用来初始化等待计数值
await0用来等待计数归零
countDown0用来让计数减一
**

案例一(es数据批量导入)

**
在这里插入图片描述
在我们项目上线之前,我们需要把数据库中的数据一次性的同步到es索引库中,但是当时的数据好像是1000万左右,一次性读取数据肯定不行(oom异常),当时我就想到可以使用线程池的方式导入,利用CountDownLatch来控制,就能避免一次性加载过多,防止内存溢出

案例二(数据汇总)

在这里插入图片描述
在实际开发的过程中,难免需要调用多个接口来汇总数据,如果所有接口(或部分接口)的没有依赖关系,就可以
使用线程池+future来提升性能

Future<Map<String, Object>> f1 = executorService.submit(() -> {
            Map<String, Object> r =
                    restTemplate.getForObject("http://localhost:9991/order/get/{id}", Map.class, 1);
            return r;
        });
        Future<Map<String, Object>> f2 = executorService.submit(() -> {
            Map<String, Object> r =
                    restTemplate.getForObject("http://localhost:9991/product/get/{id}", Map.class, 1);
            return r;
        });

        Future<Map<String, Object>> f3 = executorService.submit(() -> {
            Map<String, Object> r =
                    restTemplate.getForObject("http://localhost:9991/logistics/get/{id}", Map.class, 1);
            return r;
        });


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("order", f1.get());
        resultMap.put("product", f2.get());
        resultMap.put("logistics", f3.get());

场景3:异步线程 (线程池)

为了避免下一级方法影响上一级方法(性能考虑),可使用异步线程调用下一个方法(不需要下一级方法返回值),可以提升方法响应时间

如何控制某个方法允许并发访问线程的数量

// 1. 创建 semaphore 对象
Semaphore semaphore = new Semaphore(3);
// 3. 获取许可,计数-1
semaphore.acquire();
// 4. 释放许可 计数+1
semaphore.release();
在多线程中提供了一个工具类Semaphore,信号量。在并发的情况下,可以控制方法的访问量
1.创建Semaphore对象,可以给一个容量
2. acquire0可以请求一个信号量,这时候的信号量个数**-1**
release()释放一个信号量,此时信号量个数+1

请你谈谈Threadlocal的理解

1.ThreadLocal可以实现[资源对象]的线程隔离,让每个线程各用各的[资源对象)避免争用引发的线程安全问题
2.ThreadLocal同时实现了线程内的资源共享
3.每个线程内有一个ThreadLocalMap 类型的成员变量,用来存储资源对象
a)调用set 方法,就是以ThreadLocal自己作为 key,资源对象作为 value,放入当前线程的ThreadLocalMap 集合中
b)调用get方法,就是以ThreadLocal 自己作为 key,到当前线程中查找关联的资源值c)调用remove 方法,就是以ThreadLocal自己作为 key,移除当前线程关联的资源值
4.ThreadLocal内存泄漏问题
ThreadLocalMap中的 key 是弱用,值为强引用; key 会被GC释放内存,关联value的内存并不会释放。建议主动 remove释放 key,value
在这里插入图片描述

并发编程在许多场景下都能发挥出其独特的优势和价值,主要体现在提高系统性能、提升响应速度、优化资源利用率等方面。以下是几个典型的应用场景: ### 1. 用户界面交互(UI) 在用户界面的设计中,特别是在复杂的图形化界面或游戏开发中,并发编程可以帮助处理来自用户的输入、更新显示信息和其他后台任务的同时进行,比如数据库查询、数据加载等。通过并发,可以确保UI的实时响应和流畅性,避免由于长时间等待某些操作完成而导致的“阻塞”现象,提升用户体验。 ### 2. 网络服务器和Web服务 在网络请求处理过程中,特别是高并发场景下(如大型网站或API服务),并发编程能显著提高系统的吞吐量和响应时间。通过同时处理多个客户端请求,服务器可以在短时间内服务更多的用户,避免单一线程模型下的性能瓶颈。 ### 3. 数据处理与分析 大数据处理、机器学习和数据分析通常涉及到大量的数据集和复杂的运算流程。并发编程可以将这些任务分割成多个小部分并行执行,加速数据处理过程。例如,在分布式计算框架(如Apache Spark或Hadoop)中,数据可以被分片并分配到多个节点上同时处理,极大地提高了计算效率。 ### 4. 财务交易和风险管理 在金融领域,尤其是高频交易和风险管理系统中,每毫秒的延迟都可能导致巨大的损失。并发编程使得能够同时处理大量交易请求、市场变化监控以及其他实时数据流分析成为可能,这对于保持竞争优势至关重要。 ### 5. 游戏开发 在游戏开发中,为了实现逼真的物理引擎、高效的渲染和多人在线游戏的实时通信,需要并发处理各种复杂的任务,如碰撞检测、角色动画生成、网络数据传输等。并发编程技术能帮助游戏开发者优化这些过程,提高游戏性能和玩家体验。 ### 6. 实时操作系统(RTOS) 对于一些对实时性有极高要求的应用,如工业自动化、医疗设备、无人驾驶车辆等,并发编程通过优先级调度、时间切片等机制确保关键任务得到及时响应,保障系统的稳定性和安全性。 ### 结论 并发编程不仅适用于上述提到的高性能需求场景,还能应用于广泛的软件开发中,从简单的多任务处理到复杂的实时系统设计。合理运用并发编程技巧,可以帮助开发者解决系统效率低、响应慢等问题,实现更好的用户体验和更高的生产率。然而,同时也需要注意并发编程带来的复杂性,如死锁、竞争条件等问题,确保系统的健壮性和可靠性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值