一、概述
额,这篇博客有点水哈,就是自己拿到一个需求之后,写的模拟场景代码。不是很完善,纯属自己的一个代码记录。先描述一下需求:
现在存在着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数据结构大批量数据的处理问题,以及多线程任务调度的问题?
因为在这里考虑过用消息队列的形式处理大批量数据,额,没用上,接下来再用!