2016-09-23 5 views
1

Я хочу создать экземпляр singleton синтаксического анализатора SAX, который является потокобезопасным.Singleton thread safe SAX parser instance

Но я не могу использовать по требованию идиому, поскольку синтаксический анализатор SAX вызывает исключение SAXException, которое невозможно обработать, если оно сделало переменную класса. Вот код, который я написал.

public class Parser { 
    private static SAXParser parser; 
    Parser() throws ParserConfigurationException, SAXException { 
    if (parser==null) 
     parser=LazyHolder.factory.newSAXParser(); 
    } 
    private static class LazyHolder { 
     private static final SAXParserFactory factory=SAXParserFactory.newInstance(); 
     } 
    public SAXParser getInstance() { 
     return parser; 
    } 
} 

Есть ли лучший способ его достижения?

+0

Я не понимаю, как это должно работать. Вы хотите, чтобы несколько потоков использовали один экземпляр SAXParser? И когда один поток использует этот экземпляр, другие не могут, я прав? –

+0

Нет Я хочу, чтобы что-то вроде одного экземпляра SAXParser можно было использовать разными потоками одновременно. Это действительно возможно? –

+0

Новые экземпляры парсеров немного дорогостоящие. Есть ли эффективный способ повторного использования одинаковых экземпляров в нескольких потоках. У меня проблемы с пониманием. –

ответ

1

Но я не могу использовать по требованию идиому, поскольку синтаксический анализатор SAX вызывает исключение SAXException, которое невозможно обработать, если оно сделало переменную класса.

Если это только о получении вокруг, за исключением во время инициализации, вы можете обойти эту проблему, делая что-то вроде следующего:

public class Wrapper { 
    private static MyClassThatThrows singleton; 
    static { 
     try { 
      singleton = new MyClassThatThrows(); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 
    ... 
    public static MyClassThatThrows getInstance() { 
     return singleton; 
    } 
} 

Это будет остановить класс от загружаемой, если анализатор броски конечно.

Однако, как SAXParserFactory, так и SAXParser не являются потокобезопасными, поэтому вместо этого вы можете использовать ThreadLocal, чтобы генерировать по одному на поток.

public class Parser { 
    private final ThreadLocal<SAXParserFactory> factoryThreadLocal = new ThreadLocal<>() { 
     public SAXParserFactory initialValue() { 
      try { 
       return SAXParserFactory.newInstance(); 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 
    }; 
    public SAXParser getInstance() { 
     // you could catch and re-throw the RuntimeException if the caller should handle it 
     return factoryThreadLocal.get().newInstance(); 
    } 
} 
2

Ваше предположение, что SAXParser опасно, неправильно. см. ссылку ниже.

https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/api/javax/xml/parsers/SAXParserFactory.html

Раньше я тоже был в впечатление, что SAXParser является поточно, а иногда я использовал, чтобы получить следующее сообщение об ошибке, Это происходит, когда один поток уже использует объект парсера для разбора XML, и то же самое время другие thread также попытался использовать тот же объект. Исключение было исправлено, когда я создал экземпляр SAXParser для каждого потока.

org.xml.sax.SAXException: FWK005 parse may not be called while parsing. at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1253) ~[na:1.8.0_20] at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649) ~[na:1.8.0_20] at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:333) ~[na:1.8.0_20] at javax.xml.parsers.SAXParser.parse(SAXParser.java:195) ~[na:1.8.0_20]

 Смежные вопросы

  • Нет связанных вопросов^_^