Java UI线程被阻止 - 内存不足错误

时间:2017-09-13 09:45:04

标签: javascript java multithreading

在我的应用程序中,我每秒都会收到消息,其中包含高度,速度和航向。每次,我收到消息,我需要生成一个符号(jpg)并在桌面应用程序的UI中显示它。以下是我使用的代码。出于某种原因,只要下面的代码集成到应用程序中,我就会一直出现OutOfMemory错误。

为了摆脱它,我把下面的类的实例创建并在一个单独的线程中调用createSymbol并使svg转换为jpg转换为单独的线程。即使这样,问题仍未解决。我在想,由于此代码每秒执行一次,因此在内存中加载javascript库milsymbol.js会导致此问题。

提出我的问题,我的理解是否正确?或者你认为可能是什么问题?

如果我的理解是正确的,有没有办法,我可以在内存中加载一次库,每次都可以参考已加载的库来调用它上面的函数?

您认为以下代码有任何改进吗?

public class SymbolCreation {

    private static final Logger log =
            Logger.getLogger( UAVSymbolCreation.class );

    int altitude;
    int heading;
    int speed;

    public SymbolCreation(int altitude, int speed, int heading) {
        this.altitude = altitude;
        this.heading = heading;
        this.speed = speed;
    }

    public void createSymbol() {

        synchronized(this) {
            File milSymbolLib = new File("config/4586controller/milsymbol.js");

            if(milSymbolLib.exists()) {
                try {
                    Reader libraryReader = new FileReader(milSymbolLib);
                    ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
                    scriptEngine.eval(libraryReader);
                    SymbolCreation symbolCreation = this;
                    scriptEngine.put("symbolCreation",symbolCreation);
                    scriptEngine.eval("function run(symbolCreation){var altitude = symbolCreation.getAltitude(); "
                            + "var speedVal = symbolCreation.getSpeed(); "
                            + "var heading = symbolCreation.getHeading();"
                            + "symbolCreation.createSymbolSVG(new ms.Symbol('SFA-MFQ--------',{size:20, altitudeDepth:altitude, speed: speedVal , direction: heading}).asSVG());} run(symbolCreation);");
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ScriptException se) {
                    se.printStackTrace();
                }

            } 
        }

    }

    public void createSymbolSVG(String svgStr) {

        synchronized(this) {
            boolean fileCreated = false;
            File svgFile = new File("config/4586controller/symbol.svg");
            if(!svgFile.exists()) {
                try {
                    fileCreated = svgFile.createNewFile();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else {
                fileCreated = true;
            }

            try {
                if(fileCreated) {
                    List<String> lines = Arrays.asList(svgStr);
                    Path svgFilePath = Paths.get(svgFile.getPath());
                    Files.write(svgFilePath, lines, Charset.forName("UTF-8"));

                    //Conversion will happen on an individual thread - COMMENTED OUT 
                    convertSVGToJPEG(svgFile);

                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    public void convertSVGToJPEG(final File svgFile) {
        synchronized(this) {
            Runnable svgToJPEGConversion = new Runnable() {

                public void run() {

                    try {
                        // TODO Auto-generated method stub
                        //NOw convert svg to jpg
                        String svg_URI_input = svgFile.toURI().toString();
                        TranscoderInput input_svg_image = new TranscoderInput(svg_URI_input);        
                        //Step-2: Define OutputStream to JPG file and attach to TranscoderOutput
                        File jpgFile = new File("config/4586controller/uav.jpg");
                        if(jpgFile.exists()) {
                            jpgFile.createNewFile();
                        }

                        OutputStream jpg_ostream = new FileOutputStream(jpgFile);
                        TranscoderOutput output_jpg_image = new TranscoderOutput(jpg_ostream);              
                        // Step-3: Create JPEGTranscoder and define hints
                        JPEGTranscoder my_converter = new JPEGTranscoder();
                        my_converter.addTranscodingHint(JPEGTranscoder.KEY_QUALITY,new Float(.9));
                        // Step-4: Write output
                        my_converter.transcode(input_svg_image, output_jpg_image);
                        // Step 5- close / flush Output Stream
                        jpg_ostream.flush();
                        jpg_ostream.close();       
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    } catch (TranscoderException te) {
                        te.printStackTrace();
                    }


                }

            };

            Thread imageConversionThread = new Thread(svgToJPEGConversion);
            imageConversionThread.start();
        }

    }

    public int getAltitude() {
        return altitude;
    }

    public int getHeading() {
        return heading;
    }

    public int getSpeed() {
        return speed;
    }

}

1 个答案:

答案 0 :(得分:1)

java.io.FileReader类使用流来读取文件。 您的代码从不调用从InputStreamReader对象上的libraryReader类继承的close()方法。

您可以添加finally块以关闭阅读器或使用try-with-resources语句 - 可从Java8获得 - 因为FileReader类实现了AutoCloseable接口。

最好同时检查有多少线程处于活动状态,因为每次调用convertSVGToJPEG方法都会创建一个新线程。