package com.test.thread;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.*;
// 业务上想实现 从文件中获取数据,每100个数据启动一个线程,若最后不足100的也起一个线程,每个线程分别处理各自的源数据。
public class Test {
private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public void execute() {
long startTime = System.currentTimeMillis();
System.out.println(" ------------ execute task execute ! ------------------- "+startTime);
List<Integer> recordIds = Lists.newArrayList();
int threadNum = 1;
String fileName = "../data.txt";
File file = new File(fileName);
BufferedReader reader = null;
CompletionService<String> service = new ExecutorCompletionService<String>(executor);
int line = 1;
try {
System.out.println("以行为单位读取文件内容,一次读一整行:");
reader = new BufferedReader(new FileReader(file));
String tempString = null;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
// 显示行号
System.out.println("line " + line + ": " + tempString);
Integer recordId = Integer.valueOf(tempString.trim());
recordIds.add(recordId);
if(recordIds.size()%100==0){
service.submit(new ThreadTask(recordIds,String.valueOf(threadNum)));
recordIds.clear();
threadNum++;
}
}
if(recordIds.size()>0){
service.submit(new ThreadTask(recordIds,String.valueOf(threadNum)));
}
for (int i = 1; i <= threadNum; i++) {
try {
Future<String> future = service.take();
String result = future.get();
System.out.println(" --------------- 线程执行完成结果 :------------------- "+result);
} catch (Exception e) {
e.printStackTrace();
}
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
long endTime = System.currentTimeMillis();
System.out.println(" ------------ execute task execute ! ------------------- "+(endTime-startTime)/1000+" 秒!");
}
class ThreadTask implements Callable<String> {
private List<Integer> recordIds;
private String name;
public ThreadTask(List<Integer> recordIds,String name) {
this.recordIds = recordIds;
this.name = name;
}
@Override
public String call() throws Exception {
long startTime = System.currentTimeMillis();
if (CollectionUtils.isEmpty(recordIds)) {
return null;
}
System.out.println(name +" , recordIds.size(): " +recordIds.size()+" ------------ thread is start execute ! ---------- "+startTime);
// ... 任务处理
long endTime = System.currentTimeMillis();
System.out.println(name + " ------------ thread is end execute ! ------------ "+endTime+ "---------- 共耗时: "+(endTime-startTime)/1000+" 秒! ");
return name+ " success!";
}
}
}
提示:代码的整个流程没有问题,启用线程池,从文件中获取源数据,每100个启动一个新线程处理,问题在于,其
recordIds.clear();
recordIds是传递给每个任务线程的源数据集合,recordIds是引用类型,所以,多线程共享了源数据,简单的解决方案是:将上面的clear()删除,替换为:recordIds = Lists.newArrayList(); 最后一个需要注意的是,如果线程池如果不再使用了,需要进行关闭,executor.shutdown();