多线程用法示例
public class ContourPlot { public static GeoJson generateGeoJson(GridData gridData, double[] clipXs, double[] clipYs, double[] contourValues, Color colors[]) { GeoJson json = null; if (colors == null) { // 不填色则生成等值线(LineString类型的Geojson) } else { // 填色则生成色斑图(polygon类型的Geojson) List<Polygon> clippedPolygons = genCountourPolygons( gridData, clipXs, clipYs, contourValues); json = genGeoJson(clippedPolygons, contourValues, colors); } return json; } static class ContourCallable implements Callable<Object> { private String callableName; private GridData gridData; private List<PolyLine> lines; private List<Border> borders; private double[] contourValues; public ContourCallable(String callableName, GridData gridData, List<PolyLine> lines, List<Border> borders, double[] contourValues) { this.callableName = callableName; this.gridData = gridData; this.lines = lines; this.borders = borders; this.contourValues = contourValues; } @Override public List<wContour.Global.Polygon> call() throws Exception { System.out.println(">>>" + callableName + "任务启动"); List<wContour.Global.Polygon> contourPolygons = Contour.tracingPolygons(gridData.getGrid(), lines, borders, contourValues); System.out.println(">>>" + callableName + "任务结束"); return contourPolygons; } } private static List<wContour.Global.Polygon> genCountourPolygons(GridData gridData, double[] clipXs, double[] clipYs, double[] contourValues) { List<PointD> clipPList = new ArrayList<PointD>(); List<Border> borders = null; List<PolyLine> contourLines = null; List<wContour.Global.Polygon> contourPolygons = null; List<wContour.Global.Polygon> clippedPolygons = null; int nc = contourValues.length; int[][] S1 = new int[gridData.getGridY().length][gridData.getGridX().length]; borders = Contour .tracingBorders(gridData.getGrid(), gridData.getGridX(), gridData.getGridY(), S1, gridData.getNodata_value()); contourLines = Contour.tracingContourLines(gridData.getGrid(), gridData.getGridX(), gridData.getGridY(), nc, contourValues, gridData.getNodata_value(), borders, S1); contourLines = Contour.smoothLines(contourLines); int linesAll = contourLines.size(); int taskSize; taskSize = (linesAll <= 25) ? 1 : (linesAll <= 50) ? 2 : (linesAll <= 100) ? 3 : (linesAll <= 200) ? 6 : (linesAll <= 300) ? 9 : (linesAll <= 400) ? 12 : 16; int a = linesAll / taskSize; int b = linesAll % taskSize; ExecutorService pool = Executors.newFixedThreadPool(taskSize); List<Future<List<wContour.Global.Polygon>>> futures = new ArrayList<>(); for (int i = 0; i < taskSize; i++) { int num = a; if (i == taskSize - 1 && b != 0) num = b; int index = i * num; List<PolyLine> lineList = new ArrayList<>(); for (int j = 0; j < num; j++) { lineList.add(contourLines.get(index + j)); } Callable c = new ContourCallable("task" + i, gridData, lineList, borders, contourValues); Future<List<wContour.Global.Polygon>> f = pool.submit(c); futures.add(f); } pool.shutdown(); while (true) { // 等待所有子线程执行完 if (pool.isTerminated()) { break; } try { Thread.sleep(20); } catch (Exception e) { System.err.println("绘制色斑图线程池出错:" + e.getMessage()); } } contourPolygons = new ArrayList<>(); try { for (Future<List<wContour.Global.Polygon>> f : futures) { contourPolygons.addAll(f.get()); } } catch (Exception ex) { System.err.println("获取线程结果出错:" + ex.getMessage()); } if (clipXs == null && clipYs == null) { clippedPolygons = contourPolygons; } else { for (int i = 0; i < clipXs.length; i++) { clipPList.add(new PointD(clipXs[i], clipYs[i])); } clippedPolygons = Contour.clipPolygons(contourPolygons, clipPList); } return clippedPolygons; } static class ContourFeature implements Callable<Object> { private String callableName; private List<wContour.Global.Polygon> lineList; private double[] contourValues; private Color[] colors; public ContourFeature(String callableName, List<Polygon> lineList, double[] contourValues, Color[] colors) { this.callableName = callableName; this.lineList = lineList; this.contourValues = contourValues; this.colors = colors; } @Override public List<Feature> call() throws Exception { System.out.println("<<<" + callableName + "任务启动"); Color color = null; int index; double value; List<Feature> features = new ArrayList<Feature>(); List<com.hxgis.biz.contour.Point> points = null; List<wContour.Global.PointD> pointdList = null; com.hxgis.biz.contour.Polygon polygon = null; for (int i = 0; i < lineList.size(); i++) { value = lineList.get(i).LowValue; index = indexOfArray(contourValues, value); if (colors != null && colors.length > 1) { color = colors[index + 1]; if (!lineList.get(i).IsHighCenter) { color = colors[index]; } } points = new ArrayList<com.hxgis.biz.contour.Point>(); pointdList = lineList.get(i).OutLine.PointList; for (wContour.Global.PointD pointD : pointdList) { points.add(new Point(pointD.Y + "", pointD.X + "")); } polygon = new com.hxgis.biz.contour.Polygon(points); Map<String, Object> properties = new HashMap<String, Object>(); if (color != null) { properties.put("color", toHexEncoding(color)); } properties.put("value", value + ""); Feature feature = new Feature(); feature.setGeometry(polygon); feature.setProperties(properties); features.add(feature); } System.out.println("<<<" + callableName + "任务结束"); return features; } } /** * 生成GeoJson对象 * * @param contourPolygons 等值线多边形 * @param contourValues 等值线值 N * @param colors 等值线色卡 N-1 * @return */ private static GeoJson genGeoJson(List<wContour.Global.Polygon> contourPolygons, double[] contourValues, Color[] colors) { GeoJson json = new GeoJson(); List<Feature> features = new ArrayList<>(); int polygons = contourPolygons.size(); int taskSize = (polygons <= 25) ? 1 : (polygons <= 50) ? 2 : (polygons <= 100) ? 3 : (polygons <= 200) ? 6 : (polygons <= 300) ? 9 : (polygons <= 400) ? 12 : 16; int a = polygons / taskSize; int b = polygons % taskSize; ExecutorService pool = Executors.newFixedThreadPool(taskSize); List<Future<List<Feature>>> futures = new ArrayList<>(); for (int i = 0; i < taskSize; i++) { int num = a; if (i == taskSize - 1 && b != 0) num = b; int indexNum = i * num; List<wContour.Global.Polygon> lineList = new ArrayList<>(); for (int j = 0; j < num; j++) { lineList.add(contourPolygons.get(indexNum + j)); } Callable c = new ContourFeature("封装json线程" + i, lineList,contourValues,colors); Future<List<Feature>> f = pool.submit(c); futures.add(f); } pool.shutdown(); while (true) { // 等待所有子线程执行完 if (pool.isTerminated()) { break; } try { Thread.sleep(20); } catch (Exception e) { System.err.println("封装json线程池出错:" + e.getMessage()); } } try { for (Future<List<Feature>> f : futures) { features.addAll(f.get()); } } catch (Exception ex) { System.err.println("获取线程结果出错:" + ex.getMessage()); } json.setFeatures(features); return json; } private static String toHexEncoding(Color color) { String R, G, B; StringBuffer sb = new StringBuffer(); R = Integer.toHexString(color.getRed()); G = Integer.toHexString(color.getGreen()); B = Integer.toHexString(color.getBlue()); R = R.length() == 1 ? "0" + R : R; G = G.length() == 1 ? "0" + G : G; B = B.length() == 1 ? "0" + B : B; sb.append("#"); sb.append(R); sb.append(G); sb.append(B); return sb.toString(); } private static int indexOfArray(double[] array, double value) { int n = -1; for (int i = 0; i < array.length; i++) { if (array[i] == value) { n = i; break; } } return n; } }