思路:
用一个线程A去读取文件,将每一行放入到队列Q中;
开启多个线程B去同步的读取队列Q中的数据并发送请求;
线程A和线程B之间通过队列Q进行了交互,队列Q应该是阻塞队列;
线程A的结束,很好说,就是文件读取完毕;那么线程B什么时候结束呢?而且线程B是一组线程,又如何确保他们都正常结束呢?
下面我们先看看线程A的代码吧:
线程A是一个读取文件形成队列Q的任务,注意下面几点:
构造方法中,队列是外部传入的
定义了一个public属性END,在文件读取最后被放入到了队列中,这是为了通知线程B如果读到了END就可以结束了
放入队列中的方法用的是阻塞式的put
我们在看看线程B的代码:
首先看看属性定义以及构造方法
同样的,队列是由外部传入构造方法;为了方便,给每一个线程B一个标示。
我们重点关注下线程B的run方法:
说明:
首先是一个while循环,如果读取到了队列中的END标示,那么while结束,线程结束
这里取出队首的方法是阻塞式的take
由于队列中的一行,应该只能被一个线程B处理,因此加锁处理取出队首的过程
如果一个线程B读取到了END标示,由于END是读取并删除了,为了其他线程B尽快结束,应该将END继续放入到队列中
主程序部分:
在主程序部分,我们定义了阻塞队列及其大小,启动一个线程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,多线程实在是太恐怖了,哈哈!