高并发系统设计的15个锦囊

这就是陷阱:过度的职责分工会导致架构的复杂性和高昂的改造成本。
不要这样做:在没有充分分析的情况下,不要随意拆分数据库和表。

面试官:公司项目中Java的多线程一般用在哪些场景?

呃,这是个好问题。
不说那些虚浮的理论了,只是和大家说说我当年踩过的坑,以及如何利用多线程来解决实际问题。

我记得有一年冬天,我在上海从事一个电子商务项目。
用户量突然猛增,后端服务器直接卡住了。
当时,由于成本高昂,添加服务器不一定高效。
后来技术经理让我考虑一下多线程。
起初我很困惑,以为我不知道如何在Java中使用线程库。

1 .高并发请求处理 你是对的。
对于Tomcat这样的Web服务器来说,如果用户太多,一个请求就会被卡住,出现排队的情况。
当时,在我们的项目中,用户正在上传大文件。
如果单线程处理的话,第一个用户上传半天,第二个用户会急得骂人。
接下来发生了什么?使用线程池将文件上传到单独的线程。
主线程不需要担心这个,继续处理其他用户的请求。
就是这样,用户反馈好了很多。
记得当时的测试说,当并发数从2 00提升到6 00时,系统没有崩溃,效果立竿见影。

2 异步任务处理 你是对的。
发送电子邮件和备份之类的事情非常耗时。
如果不需要等待,用户就会不耐烦。
当时,当用户注册时,我们必须发送一封确认电子邮件。
如果我们等待电子邮件发送后再询问用户,那么所有用户都会消失。
我应该怎么办?注册成功后,主线程直接提示用户“邮件已发送”,然后开启新线程发送邮件。
用户无需等待,体验更好。
当时测试人员表示,由于这个技巧,用户注册成功率从 8 0% 提高到 9 5 %。

3 I/O 密集型操作的优化 我也陷入了你提到的这个陷阱。
之前我们都是批量的去数据库查询,但是查询结果速度极慢。
后来怎么改进的?将每个搜索放入一个单独的线程中。
我记得测试说原来需要3 4 ms,但是更改后最慢的查询需要1 2 ms。
虽然不是线性加速,但总体时间消耗却减少了。
当然,并不是所有的I/O操作都适合多线程,要看具体情况。

4 资源隔离和优先级控制 我也尝试过这个。
当时,我们的系统包括紧急订单处理和定期报告生成。
如果我们都使用线程池,紧急订单可能要等待。
接下来发生了什么?构建了两个线程池,一个专门用于处理支付,另一个用于处理报表。
我记得当时的测试说付款成功率从9 0%提高到9 9 %,因为报告请求不再阻塞付款流程。

5 复杂的数据任务 我很少遇到这种事,所以不敢乱说。
但我确实知道多线程实际上可以加快大数据处理之类的速度。
我有一个朋友,从事金融风控工作。
他使用多线程来处理数据,他的效率大大提高了。

6 计划任务和周期性操作 这个用得相当多。
我们当时做了数据备份。
如果我们使用主线程来运行它,当用户太多时系统就会冻结。
接下来发生了什么?使用 ScheduledExecutorService 每 5 分钟运行一次。
记得当时测试说系统负载减轻了,备份也准时了。

7 分布式计算框架 这事我连废话都不敢说。
我从来没有接触过这个领域。
但我确实知道,像 Hadoop 和 Spark 一样,多线程实际上可以提高集群吞吐量。

要点 我也曾踩过这些陷阱:
线程安全:共享数据不同步,直接崩溃。
我们使用ConcurrentHashMap代替HashMap,这样就避免了很多麻烦。

避免过度优化:有些任务需要序列化,强制多线程可能会适得其反。

资源争用:高并发下,如果线程池利用不好,系统会直接崩溃。
我们使用ThreadPoolExecutor来控制线程数量,效果相当不错。

水锁风险:如果水锁设计不好,系统会直接卡住。
我们花了很多时间排查锁问题来解决死锁问题。

代码示例 我看了一下你提供的代码示例,使用Future和ConcurrentHashMap其实是个好主意,可以避免重复读取,保证线程安全。
我之前使用过类似的解决方案并且效果很好。

总结 总的来说,Java多线程的核心价值在于异步和并行,但必须结合业务场景来权衡。
在Web项目中,正确使用多线程实际上可以提高响应速度和系统稳定性,尤其是在I/O密集型和分布式场景中。
效果显着。

希望我的漫谈能够对你有所帮助,不要再踩我做过的同样的陷阱。
如果您有任何疑问,请随时问我。

C语言实现高并发服务器上线程池原理(含源码)

说起来,这个线程池在高并发服务器上真是个宝。
想想看,服务器此时要接连处理这么多消息。
没有队列怎么能做到这一点?这包括接收消息、对其进行分类、创建线程、交付任务,然后线程完成工作。
最后,任务完成后需要销毁线程,这会消耗大量资源。
开销甚至更大,特别是对于内存资源稀缺的嵌入式服务器。

我记得在做一个项目时,我有一个小型 LAN 服务器并使用了线程池。
效果相当不错。
然而,一旦到达广域网或大型本地网络,并且有更多的请求进来,线程创建和销毁的频率就会增加。
那就尴尬了。
没有足够的资源。

这就是线程池的创建方式。
它不会为每个请求创建一个新线程,而是首先检查是否还有空闲线程。
如果有的话直接使用。
如果没有,他们就会排队等待。
一个线程可以完成多个任务,这样不仅节省了创建和销毁线程的成本,还提高了效率。

看看线程池的结构,真是一个复杂的系统。
它有一个任务队列,类似于超市收银员,负责收货。
一个线程集合,包括工作线程、空闲线程和待销毁线程,就像超市里的收银员负责工作一样;最后是经理线程,例如超市经理,负责监督每个人的工作并填补短缺。

作为线程池的核心,不得不提threadpool_t结构体。
它隐藏线程池状态、任务队列信息以及同步操作上的互斥锁,以确保数据一致性。

任务结构体中包含了处理函数的提示和相关参数,就像超市的收银员需要知道要收什么货,要收多少。

使用时需要将分类处理函数和参数封装成任务,然后排队等待线程执行。

如果你想学好这个东西,你需要深入了解它;如果你想进入大型互联网嵌入式开发公司,你需要掌握线程池的原理和实现。

内核学习网站也是一个不错的选择。
多读多学,实践才会有真知。