A questão é um pouco teórica, qual é o custo de criar o contexto JAXB, empacotador e não empacotador?
Descobri que meu código poderia se beneficiar mantendo o mesmo contexto JAXB e possivelmente o mesmo empacotador para todas as operações de empacotamento, em vez de criar o contexto e empacotador em cada empacotamento.
Então, qual é o custo da criação do contexto JAXB e do empacotador / desempacotador? É bom criar context + marshaller para cada operação de empacotamento ou é melhor evitá-lo?
fonte
Idealmente, você deve ter um singleton
JAXBContext
e instâncias locais deMarshaller
eUnmarshaller
.JAXBContext
instâncias são thread-safe enquantoMarshaller
eUnmarshaller
instâncias não são thread-safe e nunca devem ser compartilhadas entre threads.fonte
É uma pena que isso não esteja especificamente descrito no javadoc. O que posso dizer é que o Spring usa um JAXBContext global, compartilhado entre threads, enquanto cria um novo empacotador para cada operação de empacotamento, com um comentário javadoc no código dizendo que os empacotadores JAXB não são necessariamente seguros para encadeamento.
O mesmo é dito nesta página: https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#other-misc Miscellaneous - topics - performance - and - thread - safety .
Eu acho que criar um JAXBContext é uma operação cara, porque envolve varrer classes e pacotes para anotações. Mas medi-lo é a melhor maneira de saber.
fonte
O JAXB 2.2 ( JSR-222 ) tem isso a dizer, na seção "4.2 JAXBContext":
Infelizmente, a especificação não faz nenhuma reivindicação em relação à segurança de thread de
Unmarshaller
eMarshaller
. Portanto, é melhor supor que não.fonte
Resolvi esse problema usando:
fonte
Melhor ainda!! Com base na boa solução da postagem acima, crie o contexto apenas uma vez no construtor e salve-o em vez da classe.
Substitua a linha:
com este:
E o construtor principal com este:
portanto, no getMarshaller / getUnmarshaller, você pode remover esta linha:
Essa melhoria faz, no meu caso, que o tempo de processamento caia de 60 ~ 70ms para apenas 5 ~ 10ms
fonte
Normalmente, resolvo problemas como esse com um
ThreadLocal
padrão de classe. Dado o fato de que você precisa de um empacotador diferente para cada Classe, você pode combiná-lo com umsingleton
padrão -map.Para economizar 15 minutos de trabalho. A seguir, segue minha implementação de uma fábrica segura para threads para Jaxb Marshallers e Unmarshallers.
Permite acessar as instâncias da seguinte forma ...
E o código que você precisará é uma pequena classe Jaxb com a seguinte aparência:
fonte