爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 5017|回复: 2

求助!MeteoinfoLib java类库多线程运行时图生成异常

[复制链接]

新浪微博达人勋

发表于 2018-7-4 20:29:05 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 ertian 于 2018-7-5 11:19 编辑

王老师您好,我在使用MeteoinfoLib java类库做等值面图生成开发时,因为涉及到“批量出图且出图速度要求尽量快”的需求,所以采用了多线程调用类库来生成图片,但是发现类库在多线程下运行不正常,会出现图片之间的图形元素错乱。我写了一个用类库来执行多线程的java类,已通过附件的形式提供,,烦请王老师帮忙看下。
多线程下目前发现有两处问题:
1.各线程之间图例叠加出错,比如线程1的图上本应该叠加线程1的图例,但实际上很大概率会叠加到其它线程的图例。
TIM截图20180704202551.jpg
2.maskOut对图做处理时,会一定几率抛出Exception in thread "线程0" java.util.ConcurrentModificationException异常,导致此线程中止。
TIM截图20180704202517.jpg
java代码类
  1. package cc.htdf.meteoinfo.temp;

  2. import org.meteoinfo.data.GridData;
  3. import org.meteoinfo.data.StationData;
  4. import org.meteoinfo.data.mapdata.MapDataManage;
  5. import org.meteoinfo.data.meteodata.DrawMeteoData;
  6. import org.meteoinfo.data.meteodata.GridDataSetting;
  7. import org.meteoinfo.geoprocess.analysis.InterpolationMethods;
  8. import org.meteoinfo.geoprocess.analysis.InterpolationSetting;
  9. import org.meteoinfo.global.Extent;
  10. import org.meteoinfo.layer.VectorLayer;
  11. import org.meteoinfo.layout.*;
  12. import org.meteoinfo.legend.MapFrame;
  13. import org.meteoinfo.legend.PolygonBreak;
  14. import org.meteoinfo.map.MapView;

  15. import javax.print.PrintException;
  16. import java.awt.*;
  17. import java.io.File;
  18. import java.io.IOException;
  19. import java.util.Random;
  20. import java.util.UUID;

  21. /**
  22. * meteoinfo测试类
  23. *
  24. * @date 2018/7/4
  25. */
  26. public class TestMi implements Runnable {

  27.     private void threadMi(VectorLayer shapeLayer, StationData stationData) throws IOException, PrintException {
  28.         String threadName = Thread.currentThread().getName();
  29.         System.out.println("初始化!" + threadName);
  30.         //图片分辨率
  31.         int[] imageSize = {775, 555};
  32.         //画布大小
  33.         int[] layoutSize = {595, 410};
  34.         //画布偏移
  35.         int[] layoutOffset = {20, 105};
  36.         //创建画图
  37.         //初始化
  38.         MapLayout mapLayout = new MapLayout();
  39.         mapLayout.setBackground(new Color(255, 255, 255, 0));
  40.         mapLayout.setFont(new Font("微软雅黑", Font.BOLD, 12));
  41.         mapLayout.getLayoutMaps().get(0);
  42.         //图片分辨率
  43.         mapLayout.setSize(imageSize[0], imageSize[1]);
  44.         mapLayout.setPageBounds(new Rectangle(0, 0, imageSize[0], imageSize[1]));
  45.         mapLayout.getActiveLayoutMap().setLeft(layoutOffset[0]);
  46.         mapLayout.getActiveLayoutMap().setTop(layoutOffset[1]);
  47.         mapLayout.getActiveLayoutMap().setWidth(layoutSize[0]);
  48.         mapLayout.getActiveLayoutMap().setHeight(layoutSize[1]);
  49.         LayoutMap layoutMap = mapLayout.getActiveLayoutMap();
  50.         layoutMap.setDrawGridLine(false);
  51.         layoutMap.setDrawNeatLine(false);
  52.         layoutMap.setDrawGridLabel(false);
  53.         layoutMap.setDrawGridTickLine(false);
  54.         //创建mapView对象
  55.         MapFrame mapFrame = mapLayout.getActiveMapFrame();
  56.         MapView mapView = mapFrame.getMapView();
  57.         //格点配置
  58.         GridDataSetting gridDataSetting = new GridDataSetting();
  59.         gridDataSetting.dataExtent = shapeLayer.getExtent();
  60.         gridDataSetting.xNum = 100;
  61.         gridDataSetting.yNum = 100;
  62.         //站点插值配置
  63.         InterpolationSetting interpolationSetting = new InterpolationSetting();
  64.         interpolationSetting.setInterpolationMethod(InterpolationMethods.IDW_Neighbors);
  65.         interpolationSetting.setMinPointNum(3);
  66.         interpolationSetting.setGridDataSetting(gridDataSetting);
  67.         //站点插值成格点数据
  68.         GridData gridData = stationData.interpolateData(interpolationSetting);
  69.         //等值面分析
  70.         VectorLayer shadedLayer = DrawMeteoData.createShadedLayer(gridData, "图例(" + threadName + ")", "Data", true);
  71.         //图例配置
  72.         LayoutLegend aLegend = mapLayout.addLegend(640, 0);
  73.         aLegend.setLegendLayer(shadedLayer);
  74.         aLegend.setFont(new Font("宋体", Font.BOLD, 12));
  75.         aLegend.setLegendStyle(LegendStyles.Normal);
  76.         aLegend.setTop(mapLayout.getHeight() - aLegend.getHeight() - 30);
  77.         //裁剪
  78.         PolygonBreak aPGB = (PolygonBreak) shapeLayer.getLegendScheme().getLegendBreaks().get(0);
  79.         aPGB.setDrawFill(false);
  80.         aPGB.setOutlineColor(new Color(128, 128, 128));
  81.         aPGB.setOutlineSize(2);
  82.         mapView.addLayer(shapeLayer);
  83.         mapView.addLayer(shadedLayer);
  84.         //开启//加入掩膜
  85.         shadedLayer.setMaskout(true);
  86.         mapView.getMaskOut().setMask(true);
  87.         mapView.getMaskOut().setMaskLayer(shapeLayer.getLayerName());
  88.         mapView.zoomToExtent(shapeLayer.getExtent());
  89.         //加入标题
  90.         LayoutGraphic lTitle = mapLayout.addText("等值面(" + threadName + ")", mapLayout.getWidth() / 2, 40, 40);
  91.         lTitle.setTop(15);
  92.         //刷新配置
  93.         mapView.paintLayers();
  94.         mapView.repaint();
  95.         //输出图片
  96.         String outPutFileUrl = "E:\\OUT_PUT\" + UUID.randomUUID().toString().substring(0, 7) + "_" + threadName + ".png";
  97.         //建立父目录
  98.         new File(outPutFileUrl).mkdirs();
  99.         mapLayout.exportToPicture(outPutFileUrl);
  100.         System.out.println("生成成功!" + Thread.currentThread().getName());
  101.     }

  102.     @Override
  103.     public void run() {
  104.         //任意导入一个省份的轮廓shape图层
  105.         String shapeUrl = "E:\\shp\\河南省_province.shp";
  106.         //获取数据
  107.         VectorLayer shapeLayer = null;
  108.         try {
  109.             shapeLayer = MapDataManage.readMapFile_ShapeFile(shapeUrl);
  110.         } catch (Exception e) {
  111.             e.printStackTrace();
  112.         }
  113.         if (shapeLayer == null) {
  114.             System.out.println("shape读取出错!");
  115.             return;
  116.         }
  117.         //经纬度范围
  118.         Extent extent = shapeLayer.getExtent();
  119.         //随机站点数据
  120.         int sNum = 100;
  121.         StationData stationData = new StationData();
  122.         for (int i = 0; i < sNum; i++) {
  123.             double lon = new Random().nextDouble() * (extent.maxX - extent.minX) + extent.minX;
  124.             double lat = new Random().nextDouble() * (extent.maxY - extent.minY) + extent.minY;
  125.             double value = new Random().nextInt(70) + 15;
  126.             stationData.addData("", "", lon, lat, value);
  127.         }
  128.         //生成图形
  129.         try {
  130.             threadMi(shapeLayer, stationData);
  131.         } catch (IOException | PrintException e) {
  132.             e.printStackTrace();
  133.         }
  134.     }

  135.     public static void main(String[] args) throws Exception {
  136.         int threadNum = 8;
  137.         TestMi testMi = new TestMi();
  138.         for (int i = 0; i < threadNum; i++) {
  139.             Thread thread = new Thread(testMi);
  140.             thread.setName("线程" + i);
  141.             thread.start();
  142.             Thread.sleep(2000);
  143.         }
  144.     }
  145. }
复制代码




TestMi.java

6.15 KB, 阅读权限: 1, 下载次数: 7, 下载积分: 金钱 -5

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2019-12-30 11:12:52 | 显示全部楼层
为什么单独运行这个类会报错呢, mapLayout.getLayoutMaps().get(0);这个方法包空指针
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-6-13 10:04:17 | 显示全部楼层
请问解决了吗?能告知吗?我现在正在学习,需要这方面的内容
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表