2017-11-30 9 views
0

目的 - サックスパーサーを使用して別のxmlファイルを解析することにより、並列に 複数のスレッドが生成されます。マルチスレッド - SaxParser複数のxmlファイルをパラレルに解析する

同じトピックに関連する複数の投稿が見つかりました。しかし、誰も答えを指していません。

Question 1Question 2

私はSAXParserFactoryのとSAXParserのは、スレッドセーフではありません知っています。私の研究では、スレッドごとにSAXParserFactoryとSAXParserの新しいインスタンスを作成する必要があります。 これをどうすれば実現できますか? (MySAXHandlerの新しいインスタンス)

私のコードの現在の実装を見てください。

開始のSAXParser

@Override 
public GameStatisticsDTO processStatsGameStatXML(File gameStatsStatFile) { 
    try(InputStream inputStream = new FileInputStream(gameStatsStatFile)) { 
     // New Handler instance 
     GameStatsSAXHandler gameStatsSAXHandler = new GameStatsSAXHandler(); 

     Reader reader = new InputStreamReader(inputStream, Constants.ENCODING_TYPE_UTF_8); 
     InputSource inputSource = new InputSource(reader); 
     inputSource.setEncoding(Constants.ENCODING_TYPE_UTF_8); 

     // New Instance of SAXParserFactory 
     SAXParserFactory factory = SAXParserFactory.newInstance(); 
     factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); 

     // New Instance of SAXParser 
     SAXParser saxParser = factory.newSAXParser(); 

     // Create an XML reader to set the entity resolver. 
     XMLReader xmlReader = saxParser.getXMLReader(); 
     xmlReader.setEntityResolver(new StatsCustomResolver()); 
     xmlReader.setContentHandler(gameStatsSAXHandler); 
     xmlReader.parse(inputSource); 
     return gameStatsSAXHandler.getGameStatisticsDTO(); 
    } catch (Exception e) { 
     throw new UnprocessableEntityException(); 
    } 
} 

のこれは、XMLノードを解析するGameStatsSAXHandlerを呼び出します。 Within that class I'm maintaining Instance reference variables to store my parsed data.

public class GameStatsSAXHandler extends DefaultHandler { 

    // Instance Reference Variable - Hope this is thread safe 
    private GameStatisticsDTO gameStatisticsDTO = new GameStatisticsDTO(); 

    protected GameStatisticsDTO getGameStatisticsDTO() { 
     return this.gameStatisticsDTO; 
    } 

    @Override 
    public void startElement (String uri, String localName, String 
    elementName, Attributes attributes) throws SAXException { 
     // Process the data and add it to the gameStatisticsDTO 
    } 

    @Override 
    public void endElement (String uri, String localName, String 
     elementName) throws SAXException { 
     // Do some processing in gameStatisticsDTO 
    } 
} 

gameStatisticsDTOは、複数のインスタンスの参照変数(オブジェクトとリスト)

は、だから私は2つの質問を持っているが含まれています。

1)ローカルプリミティブ変数はスレッドセーフであるため、これは GameStatsSAXHandlerとそのGameStatisticsDTOはスレッドセーフですか?

私の考え:スレッドごとに新しいGameStatsSAXHandlerインスタンスを作成すると、GameStatisticsDTOはスレッドセーフになります。

2)どうすれば の並列性を持つマルチスレッド環境に変換できますか。

私の思想:ThreadPoolExecutorを作成し、新しいのSAXParserFactoryを渡し、新しいSAXParserのを発生し、新しいGameStatsSAXHandlerを作成し、処理に基本メソッドに渡します。 (processStatsGameStatXMLメソッド)

しかし、スレッドごとに新しいインスタンスを作成するにはどうすればよいですか?コードサンプルは素晴らしいでしょう! ありがとう

+0

最初はマルチスレッドである必要がありますか? SAXは正しい解析モデルですか? –

答えて

0

ThreadPoolExecutorにタスクを送信します。タスクは、通常、特定のタスクに関連する状況、つまり状態、データ、すべての場合、1つのファイルの解析を保持する場所です。

したがって、このような何か:

class ParsingTask implements Runnable { 
    private SAXParserFactory factory; 
    private SAXParser parser; 
    private GameStatsHandler handler; 
    // whatever else needed for parsing 

    @Override 
    public void run() { 
     // actual parsing code 
    } 
} 

[編集]サイドノートで、私はSAXParserFactoryの通常の実装は、スレッドセーフであると思います。異なる構文解析タスク間で異なる方法でファクトリを構成する必要がある場合を除き、新しい解析タスクごとに毎回インスタンス化する必要はありません。

+0

@jingx返信ありがとうございます。しかし、SAXParseFactoryはスレッドセーフではありません。[oracle impl](https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/api/javax/xml/parsers/SAXParserFactory.html)。だから私は各スレッドごとに1つのインスタンスを作成する必要があります。私はそのビット高価を知っています。 – Neero

+0

これはオラクルの 'SAXParserFactory'の実装ではなく、インタフェース自体です。また、[JDK 8](https://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/SAXParserFactory.html#newInstance--)の時点でJDK 1.5を参照しており、糸の安全に関する部分が削除されました。 あなたが使用しているパッケージから実装クラスを探し、_its_ドキュメントを読んでスレッドセーフであるかどうかを判断します。 – jingx

+0

はい、私の悪いです。私は1.5の文書を参照しています。それを指摘してくれてありがとう。 – Neero

関連する問題