【多线程 4】多线程实例(实例分析博客在下一篇)

一、概述

额,这篇博客有点水哈,就是自己拿到一个需求之后,写的模拟场景代码。不是很完善,纯属自己的一个代码记录。先描述一下需求:

现在存在着N个点(注意:N个代码大批量数据),这N个点(对象Point)存放在一个动态数组里。每个点包含有X和Y属性!当这些点与已知点的距离,不小于D时,为正常数据,反之,则为异常数据,需要将这些数据剔除!


二、分析

1,首先建立一个point对象,包含X和Y属性

2,编写计算两点之间距离的方法

3,编写一个方法,模拟大批量数据(嘿嘿,这里就模拟了50个,见笑了)

4,编写一个方法,找出异常数据

5,编写主程序,得出最终符合条件的结果


三、代码

3.1,Point的代码就省略了,private double x; private doubley; 然后,创建各自的get 和set 方法

3.2,distance()计算两点间的距离

<span style="font-family:KaiTi_GB2312;font-size:18px;">	/**
	 * 计算两点之间的距离
	 * 
	 * @param basePoint 原点,对比点
	 * @param current 当前获取的点
	 * @return 两点间的距离
	 */
	public static double distance(Point basePoint, Point current) {// 求两点的距离
		return (double) Math.sqrt((current.getX() - basePoint.getX())
				* (current.getX() - basePoint.getX())
				+ (current.getY() - basePoint.getY())
				* (current.getY() - basePoint.getY()));
	}</span>

3.3,init()模拟数据

<span style="font-family:KaiTi_GB2312;font-size:18px;">/**
	 * 初始化已知条件,待查找数量为50个
	 */
	public static List<Point> init() {
		// 第一题,声明一个动态数组
		List<Point> ary = new ArrayList<Point>();

		// 赋值ary数组,假设有50个
		for (int i = 0; i < 50; i++) {
			// 利用随机生成函数,生成X和Y
			Random rand = new Random();
			double x = rand.nextDouble() * 10.0 + 0;
			double y = rand.nextDouble() * 10.0 + 0;
			Point MyPoint = new Point();
			MyPoint.setX(x);
			MyPoint.setY(y);
			ary.add(MyPoint);

		}
		return ary;
	}</span>

3.4,findTheEle()找出异常数据

<span style="font-family:KaiTi_GB2312;font-size:18px;">	/**
	 * 找出小于d的数据
	 */
	@SuppressWarnings("finally")
	public static List<Point> findTheEle(List<Point> ary, Point basePoint,
			double d) {
		// 启用线程的数量
		int ThreadNum = ary.size() / 11;
		// 接收结果的list
		List<Point> listResult = new ArrayList<Point>();

		Future<String> future = null;

		// 如果任务没有平均分配完,则增加一个线程
		int remainTask = ary.size() % 11;
		if (remainTask > 0) {
			ThreadNum += 1;
		}

		// 启动ThreadNum个定长线程,同时计算
		ExecutorService threadPool = Executors.newFixedThreadPool(ThreadNum);
		
		for (int i = 0; i < ThreadNum; i++) {
			int threadNum = i;
			// 使用submit方法,捕获线程执行结果(execute没有返回结果)
			future = threadPool.submit(new Callable<String>() {
				public String call() {
					for (int j = threadNum * 11; j < 11 + 11 * threadNum; j++) {
						Point current = ary.get(j);
						double distance = distance(basePoint, current);
						if (distance < d) {
							listResult.add(current);
						}
						System.out.println(Thread.currentThread().getName()
								+ "正在计算第" + j + "个点!" + "当前为第" + threadNum+ "个任务!");
						if (j == ary.size() - 1) {
							break;
						}
					}
					return "success";
				}
			});

		}

		try {
			//如果线程池里还有正在执行计算的线程
			if (threadPool.isTerminated() == false) {
				boolean isCompletion = false;
				do {
					try {
						// 阻塞主线程,直到线程池里所有任务结束
						isCompletion = !threadPool.awaitTermination(2,TimeUnit.SECONDS);
					} catch (InterruptedException e) {
						e.printStackTrace();
					} 
				} while (isCompletion == false);
			}
			System.out.println("查找距离小于d的任务结果:" + future.get());
			System.out.println("不符合的点共有:" + listResult.size() + "个");

		} catch (InterruptedException | ExecutionException e) {
			System.out.println(e.getCause().getMessage());
		} finally {
			threadPool.shutdown();
		}
		return listResult;
	}</span>

3.5,主程序

<span style="font-family:KaiTi_GB2312;font-size:18px;">	// 主程序,从大批量数据中,查找符合条件的部分
	public static void main(String[] arg) {

		Point basePoint = new Point();// 假设currpoint当前点为原点;
		basePoint.setX(0);
		basePoint.setY(0);
		double d = 5;
		List<Point> list = new ArrayList<Point>();
		list = init();
		System.out.println("原始数据共有:" + list.size());
		List<Point> theWrongData = findTheEle(list, basePoint, d);

		// 剔除脏数据之后的结果
		list.removeAll(theWrongData);
		System.out.println("符合条件的数据共有:" + list.size());

	}</span>

四、总结

当时拿到这个需求的时候,想到了优化方案就是分割list,然后启用多线程同时计算。额,有点瑕疵,但是也算是任务完成。下篇博客再来介绍这里面的问题,比如说,线程池有哪几种类型,各自的应用场景是什么?同时启动了几个线程,万一线程死了,或者执行任务失败了怎么办?为什么用了submit方法而不是execute方法?为什么使用了阻塞线程?还有就是,list数据结构大批量数据的处理问题,以及多线程任务调度的问题?

因为在这里考虑过用消息队列的形式处理大批量数据,额,没用上,接下来再用!

原文地址:https://www.cnblogs.com/hhx626/p/7534630.html