2017-11-30 20 views
0

목표 - 색소 파서를 사용하여 다른 xml 파일 paralleley를 다중 스레드로 구문 분석합니다.멀티 스레딩 - SaxParser 여러 xml 파일의 구문 분석 paralaley

같은 주제와 관련된 여러 게시물을 찾았습니다. 그러나 그들 중 아무도 대답을 지적하고 있지 않습니다.

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 여러 인스턴스 참조 변수 (개체 및 목록)

그래서 나는이 개 질문이 포함되어 있습니다.

1) 로컬 기본 변수 만이 스레드로부터 안전하기 때문에. 이게 GameStatsSAXHandler와 GameStatisticsDTO는 스레드로부터 안전합니까?

내 생각 : 각 스레드에 대해 새로운 GameStatsSAXHandler 인스턴스를 생성하면 GameStatisticsDTO는 스레드로부터 안전합니다.

2) 어떻게 이것을 병렬 처리로 다중 스레드 환경으로 변환 할 수 있습니까?

내 생각 : 가능한 ThreadPoolExecutor를 작성하고 새의 SAXParserFactory을 전달하고 새로운 SAXParser를를 생성하고 새로운 GameStatsSAXHandler를 생성하고 처리 기본 방법에 전달합니다. (processStatsGameStatXML 메서드)

그러나 각 스레드에 대해 새 인스턴스를 만들려면 어떻게해야합니까? 코드 샘플이 좋습니다! 감사합니다.

+0

처음부터 멀티 스레딩해야합니까? SAX는 올바른 구문 분석 모델입니까? –

답변

0

ThreadPoolExecutor에게 작업을 제출합니다. 작업은 일반적으로 모든 상황 별, 즉 상태, 특정 작업과 관련된 데이터, 사용자의 경우 한 파일의 구문 분석을 유지하는 곳입니다.

그래서 이런 식으로 뭔가 :

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). 그래서 각 스레드에 대해 하나의 인스턴스를 만들어야합니다. 나는 조금 비싸다는 것을 안다. – Neero

+0

그건 오라클의'SAXParserFactory' 구현이 아니라 인터페이스 자체입니다. 또한 [JDK 8] (https://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/SAXParserFactory.html#newInstance--) 현재 JDK 1.5를 참조하고 있으며, thread-safety에 관한 부분은 삭제되었습니다. 사용중인 패키지에서 구현 클래스를 찾고 _its_ 문서를 읽고 스레드 안전 여부를 결정하십시오. – jingx

+0

네, 제 잘못입니다. 내가 1.5 의사를 말하는거야. 그것을 지적 주셔서 감사합니다. – Neero