Java--如何使用多线程对一个HashSet进行并行计算

这段时间工作比较忙。今天抽空整理了一个多线程使用场景。

当处理一个数据量比较大的集合时(每个元素的计算都耗时比较长)。由于只使用一个线程进行计算比较慢。所以想到多跑几个线程进行处理。

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的值,有兴趣的朋友可以自己尝试一下。也是可以的哦~~

 

喜欢的朋友点个赞哦~~

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stalin_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值