这段时间工作比较忙。今天抽空整理了一个多线程使用场景。
当处理一个数据量比较大的集合时(每个元素的计算都耗时比较长)。由于只使用一个线程进行计算比较慢。所以想到多跑几个线程进行处理。
1.每个线程可以自行计算要处理集合的开始和结束索引,确保每一个元素都被计算的到。
2.同时为了防止这个集合中数据的长度有变化,需要线程每一次计算前都重新获取集合长度,重新计算该线程要计算这个集合的开始和结束索引。
3.线程数是通过xml配置来进行修改的。不用每次修改代码来改动线程数。
代码如下:
Main:(主函数的类)
/**
* 使用可配置的多个线程来对一个大数据量的集合进行计算,每个线程计算其中的一部分数据。 线程每隔一段时间根据数据集合计算自身要计算的索引。然后再做计算。
*
* @author Stalin 2018年9月21日上午9:51:04
*/
public class Main {
public static Set<String> set = new HashSet<>();
public static int count;
public static void main(String[] args) {
// 为set添加10w条数据
for (int i = 0; i < 100000; i++) {
set.add("/home/test/dir" + i);
}
// 获取线程总数量
count = getCount();
// 根据线程数创建足够的线程
for (int i = 1; i <= count; i++) {
Timer t = new Timer(i);
t.start();
System.out.println("这是第" + i + "个线程,线程总数:" + count);
}
}
// 获取配置文件中的线程数量
public static int getCount() {
int count = 1;
SAXReader reader = new SAXReader();
try {
Document document = reader.read(new File("etc/config.xml"));
Element root = document.getRootElement();
count = Integer.valueOf(root.element("Config").elementText("ThreadCount"));
} catch (Exception e) {
e.printStackTrace();
return count;
}
return count;
}
}
Timer(计算线程):
public class Timer extends Thread {
private int startIndex;
private int endIndex;
private int index;
public int getStartIndex() {
return startIndex;
}
public void setStartIndex(int startIndex) {
this.startIndex = startIndex;
}
public int getEndIndex() {
return endIndex;
}
public void setEndIndex(int endIndex) {
this.endIndex = endIndex;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public Timer(int index) {// 根据传入的线程号,可以计算出开始索引和结束索引
this.index = index;
}
@Override
public void run() {
while (true) {
List<String> timeList = new ArrayList<>();
// 将set的全部元素添加到list当中
timeList.addAll(Main.set);
// 根据当前线程传入的索引值计算要计算的开始索引和结束索引
if (timeList.size() != 0) {
startIndex = 1 + (Main.set.size() / Main.count * (index - 1));
endIndex = 0 + (Main.set.size() / Main.count * index);
if (index == Main.count) {// 最后一个线程,结束索引为set的最后一个下标。
endIndex = Main.set.size() - 1;
} else if (index == 1) {// 第一个线程,开始索引应该为0,
startIndex = 0;
}
System.out.println("这是第:" + index + "个计算线程,开始索引/结束索引:" + startIndex + "/" + endIndex);
// 进行计算
int num = 0;
for (int i = startIndex; i <= endIndex; i++) {
if (timeList.get(i) != null) {
num++;
}
}
System.out.println("线程" + index + "计算了" + num + "个目录");
}
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Config>
<ThreadCount>5</ThreadCount>
</Config>
</Root>
运行结果如下:
由于我只是举个例子,没有在这里一直更新set的值,有兴趣的朋友可以自己尝试一下。也是可以的哦~~
喜欢的朋友点个赞哦~~