2017-09-13 15 views
0

私のアプリケーションでは、高度、速度、見出しを含む1秒ごとにメッセージが表示されます。メッセージが表示されるたびに、シンボル(jpg)を生成してデスクトップアプリケーションのUIに表示する必要があります。以下は、私が使用したコードです。何らかの理由で、以下のコードがアプリケーションに統合されるとすぐに、OutOfMemoryエラーが発生します。Java UIスレッドがブロックされました - メモリ不足エラー

これを取り除くために、私はインスタンス作成をクラスの下に置き、別のスレッドで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; 
    } 

} 
+0

なぜメソッドを同期させるのではなく、どこでも 'synchronized(this)'を使用していますか? – Kayaman

+0

インスタンスの代わりにクラスにロックを適用したいからです。スレッドごとに新しいインスタンスを作成するためです。なぜなら、私はこのメソッドに作用する異なるインスタンスを作ることができないからです。私は、メッセージが来るとシンボルの作成を逐次的にしたいと思っています。 – User

+0

しかし、 'this'はクラスではなく、現在のインスタンスです。 'public synchronized void createSymbolSVG(..'。 – Kayaman

答えて

1

java.io.FileReaderクラスはストリームを使用してファイルを読み取ります。 コードでlibraryReaderオブジェクトのInputStreamReaderクラスから継承したclose()メソッドを呼び出すことはありません。利用可能Java8から - - FileReaderクラスがAutoCloseableインタフェースを実装しているので

あなたがtry-with-resources文を読者を閉じるか、使用するためにfinallyブロックを追加することができます。


convertSVGToJPEGメソッドへの各呼び出しは、新しいスレッドを作成しますので、それは、同時に生きているどのように多くのスレッドをチェックしても良いでしょう。

+0

@Kayaman私はKayamanの努力も感謝するだろう。問題を詳細に解決する – User

+0

@nathan答えを見つけたが間違って提示した努力を感謝する – User