您的位置:首页 > 编程语言 > Java开发

Java 并发读取List

2016-02-16 20:32 323 查看
JAVA里面有一个并发容器CopyOnWriteArrayList用于支持并发读写List 容器,稍微查了下这个说明,这个容器在并发写的情况下效率很低。因此使用场景应该在并发读远大于并发写的情况下使用这个容器。

这里写了一个多线程程序来读取现有的list对象。上代码:

package com.lenovo.plm.dms.p1;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {

public static void main(String[] args) {

List<String> list = new ArrayList<String>();
Map<Long,Integer> map = new HashMap<Long,Integer>();
for(int i = 0;i<1000;i++){
list.add(""+i);
}

int pcount = Runtime.getRuntime().availableProcessors();

long start = System.currentTimeMillis();

for(int i=0;i<pcount;i++){

Thread t = new MyThread1(list,map);
map.put(t.getId(),Integer.valueOf(i));
t.start();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// System.out.println(list.get(i));
}

System.out.println("----"+(System.currentTimeMillis() - start));
}

}


线程类如下:
package com.lenovo.plm.dms.p1;

import java.util.List;
import java.util.Map;

public class MyThread1 extends Thread {

private List<String> list;
private Map<Long,Integer> map;

public MyThread1(List<String> list,Map<Long,Integer> map){
this.list = list;
this.map = map;
}

@Override
public void run() {
// TODO Auto-generated method stub

int pcount = Runtime.getRuntime().availableProcessors();
int i = map.get(Thread.currentThread().getId());

for(;i<list.size();i+=pcount){
System.out.println(list.get(i));
}

}

}


最后运行的时间是:34

这里单独写了个单线程的类来读取这个list对象,使用的时间是22,单线程读取这个list比多线程还快。说明多线程的调度也比较消耗时间。但并不能说明多线程一定慢,如果针对list读取又继续做了复杂的数据处理,那么多线程速度会快很多。

这里需要说明一点是程序里面使用了join方法。这里join方法的使用是为了让主线程在其他线程结束后来记录整个读取list的时间。换句话说join的使用按照如下逻辑:

在当前线程中调用t.join,则当前线程必须等到t线程结束后才能继续执行。这个join也可以传入long类型的参数,表示当前线程要等待的ms数。

最后一个需要说明的问题是:多线程数量的问题,一般情况下,多线程数量要等于机器CPU核数-1. 原理很简单,并发是在多个核心上计算,如果超过核心数,则多余的线程必须等待,这样效率不会再提高,反而因为调度消耗性能。 这个结论是在<<JAVA并发编程实践>> 这本书里面有。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 多线程