初学多线程,分批处理list值的时候速度居然不如直接打印?
刚学习多线程,想试着用它解决处理大的集合的情况,创建一个size为900000的list,创建三个线程,每个线程打印300000个。处理的速度居然小于我用for循环直接循环打印的速度,附上代码如下:
package com.practice.concurrent.dealwithlist;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DealWithListTest {
private static ExecutorService executorService = Executors.newCachedThreadPool();
private static Lock lock = new ReentrantLock();
private static List<String> list = new ArrayList<String>();
static {
for (int i=0; i<900000; i++){
list.add(i + "str");
}
}
//分三段打印数据
private static void dealwith(int i){
lock.lock();
try{
List<String> childList = list.subList(i*300000 , (i+1)*300000);
for (String s : childList){
System.out.println(Thread.currentThread() + "------------" + s);
}
}finally {
lock.unlock();
}
}
private static class Task implements Runnable{
private int i;
public Task(int i){
this.i = i;
}
@Override
public void run() {
dealwith(i);
}
}
public static void main(String[] args) {
long before = System.currentTimeMillis();
/**
* 使用多线程耗时2830毫秒
*/
for (int i = 0; i <3 ; i++) {
executorService.execute(new Task(i));
}
executorService.shutdown();
while (true){
if (executorService.isTerminated()){
System.out.println("所有线程执行结束");
break;
}
}
/**
* 直接打印耗时2102毫秒
*/
// for (String s : list){
// System.out.println(s);
// }
System.out.println("整体耗时" + (System.currentTimeMillis()-before) + "毫秒");
}
}
一定是我对线程的理解不够深入,希望大家给予批评指正。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
上面程序里我主要有以下几个问题:
1.lock并没有任何作用,因为这里不涉及到共享资源的争夺,list我是切分为完全不同的三段来处理的。
2.如楼上几位朋友所说,system.out.println()是同步方法,开销较大。
3.如@Ezio一楼所说,多线程多用于处理计算密集型操作。所以这里的打印是不应该的。
所以我做了如下更改,其中
1.我把打印操作改为了“为list里的每个对象后面添加一个字符串”;
2.list里的元素由String改为StringBuffer类型,因为String对象是不可修改的,每次修改其实都是废弃了原对象,建立了新对象,也是比较消耗时间的。
新代码如下:
这里list的size改为了9000000,但是最终的处理结果居然从几千毫秒到 一百多 二百多毫秒。好刺激!
对多线程处理的测试结果也比较乐观
线程处理 148毫秒
单线程处理 288毫秒
如有理解问题,望指正。
打印是IO密集操作,用多线程还增加了线程切换的耗时……
多线程应该用来做计算密集的操作
你这
ReentrantLock
是用来做什么的?为什么要要求抢占锁的线程释放锁其他线程才能执行?println
本来就是同步方法多个线程只会徒增等待。你加上ReentrantLock相当于单线程执行了,每个线程都要等待其它线程释放了锁才能执行。
另外,System.out.println的开销相对比较大的,是程序里的主要瓶颈