队列在多线程中的应用

简介:

前言

最近遇到一个问题:有一个几十万行的数据文件,需要提取每一行中的特定字段去请求数据。每一次请求数据可能花费100毫秒的时间,这样的话,如果我们单线程顺序读取文件,发送请求,时间开销很大。如何缩短时间呢?自然想到了多线程处理。可惜自己多线程程序写的并不多,昨晚折腾了许久,终于有所收获!


单线程处理


直接看代码吧:


wKioL1W9flSCpKdqAAFiH8w4feg489.jpg



为了方便,用Thread.sleep的方式进行模拟发送请求获取数据。


运行结果如下:


单线程读取文件并发请求耗时:506047


在单线程处理的情况下,仅仅5000多条数据,就花费了8分多钟!



队列+多线程处理

思路:


用一个线程A去读取文件,将每一行放入到队列Q中;


开启多个线程B去同步的读取队列Q中的数据并发送请求;


线程A和线程B之间通过队列Q进行了交互,队列Q应该是阻塞队列;


线程A的结束,很好说,就是文件读取完毕;那么线程B什么时候结束呢?而且线程B是一组线程,又如何确保他们都正常结束呢?



下面我们先看看线程A的代码吧:


wKioL1W9g42ymrYcAAIsgS8ufGo972.jpg


线程A是一个读取文件形成队列Q的任务,注意下面几点:


  • 构造方法中,队列是外部传入的


  • 定义了一个public属性END,在文件读取最后被放入到了队列中,这是为了通知线程B如果读到了END就可以结束了


  • 放入队列中的方法用的是阻塞式的put



我们在看看线程B的代码:


首先看看属性定义以及构造方法


wKiom1W9g52QJvXEAADdQvnE6TI311.jpg


同样的,队列是由外部传入构造方法;为了方便,给每一个线程B一个标示。


我们重点关注下线程B的run方法:


wKioL1W9hijz2dUoAAHqWTVDo50480.jpg


说明:


  • 首先是一个while循环,如果读取到了队列中的END标示,那么while结束,线程结束


  • 这里取出队首的方法是阻塞式的take


  • 由于队列中的一行,应该只能被一个线程B处理,因此加锁处理取出队首的过程


  • 如果一个线程B读取到了END标示,由于END是读取并删除了,为了其他线程B尽快结束,应该将END继续放入到队列中



主程序部分:


wKioL1W9iBGDfOKoAAILDd0fSJg242.jpg


在主程序部分,我们定义了阻塞队列及其大小,启动一个线程A,以及多个线程B。


运行结果:


线程[13] 处理167

线程[22] 处理167

线程[28] 处理167

线程[1] 处理167

线程[29] 处理167

线程[27] 处理167

线程[25] 处理167

线程[21] 处理167

线程[18] 处理167

线程[20] 处理167

线程[0] 处理168

线程[4] 处理168

线程[19] 处理168

线程[7] 处理168

线程[15] 处理168

线程[23] 处理168

线程[14] 处理168

线程[3] 处理168

线程[17] 处理168

线程[8] 处理168

线程[5] 处理168

线程[2] 处理168

线程[6] 处理168

线程[24] 处理168

线程[12] 处理168

线程[9] 处理168

线程[11] 处理168

线程[16] 处理168

线程[26] 处理168

线程[10] 处理168

队列 + 多线程同步 读取文件并发请求耗时:16921


可以发现,现在5000多行文件的处理,从原来的8分多钟,变成了现在的16S,多线程实在是太恐怖了,哈哈!


本文转自zfz_linux_boy 51CTO博客,原文链接:http://blog.51cto.com/zhangfengzhe/1680939,如需转载请自行联系原作者


相关文章
|
23天前
|
缓存 安全 C++
C++无锁队列:解锁多线程编程新境界
【10月更文挑战第27天】
36 7
|
23天前
|
消息中间件 存储 安全
|
29天前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
1月前
|
监控 Java
在实际应用中选择线程异常捕获方法的考量
【10月更文挑战第15天】选择最适合的线程异常捕获方法需要综合考虑多种因素。没有一种方法是绝对最优的,需要根据具体情况进行权衡和选择。在实际应用中,还需要不断地实践和总结经验,以提高异常处理的效果和程序的稳定性。
22 3
|
1月前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
49 4
|
1月前
|
数据采集 存储 Java
Crawler4j在多线程网页抓取中的应用
Crawler4j在多线程网页抓取中的应用
|
1月前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
31 3
|
1月前
|
Java 数据处理 数据库
Java多线程的理解和应用场景
Java多线程的理解和应用场景
54 1
|
27天前
|
Java 开发者
Java中的多线程基础与应用
【10月更文挑战第24天】在Java的世界中,多线程是提高效率和实现并发处理的关键。本文将深入浅出地介绍如何在Java中创建和管理多线程,以及如何通过同步机制确保数据的安全性。我们将一起探索线程生命周期的奥秘,并通过实例学习如何优化多线程的性能。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往高效编程的大门。
17 0
|
1月前
|
存储 运维 API
源码解密协程队列和线程队列的实现原理(一)
源码解密协程队列和线程队列的实现原理(一)
35 1
下一篇
无影云桌面