Pergunta

Eu estou tentando solucionar uma falha intermitente que parece estar relacionada com a remoção de um objeto de um HashMap e, em seguida, colocar o mesmo objeto volta usando uma nova chave. Meu HashMap é criado da seguinte forma:

transactions = new HashMap<Short, TransactionBase>();

O código que faz a re-atribuição é a seguinte:

transactions.remove(transaction.tran_no);
transaction.tran_no = generate_transaction_id();
transactions.put(transaction.tran_no, transaction);

O comportamento intermitente que eu estou vendo é que o código que executa imediatamente após este que depende do objeto de transação ser localizável não parece encontrar o objeto de transação usando o novo ID de transação. No entanto, em algum momento futuro, a transação pode ser localizado. Então, puxando em palhas, existe algum tipo de efeito assíncrono para put () ou remover que pode causar este tipo de comportamento?

Eu devo mencionar que, para o melhor de meu conhecimento, o recipiente está sendo acessado por apenas um segmento. Já li em que ele documentação que HashMap classe não é "sincronizado".

Foi útil?

Solução

Não há nenhum efeito "assíncronos" na classe HashMap. Assim que você colocar alguma coisa lá dentro, ele está lá. Você deve um duplo e triplo verificar para se certificar de que não existem problemas de segmentação.

A única coisa que posso pensar é que você está fazendo uma cópia do lugar HashMap. A cópia, obviamente, não será afetado por você adicionar coisas para o original, ou vice-versa.

Outras dicas

Há uma ligeira diferença entre remover / get e put (embora o meu palpite é que você tem um problema de segmentação).

O parâmetro para remove / get é do tipo Object; para put é do tipo K. A razão para isso foi dito muitas vezes antes. Isso significa que ele tem problemas com o boxe. Eu não estou indo para adivinhar quais são as regras. Se um valor é embalado como um Byte em um lugar e um Short em outro, então esses dois objetos não podem ser iguais.

Há um problema semelhante com List.remove(int) e List.remove(Object).

Eu presumo que toda vez que você verificar a presença do item que você está definitivamente usando um short ou Short argument para Map.get() ou Map.contains()?

Estes métodos levam argumentos objeto para se você passar-lhes uma int ele será convertido para um Integer e nunca irá corresponder a qualquer item em seu mapa porque todos terão chaves Short.

Apenas uma sugestão ... você está focando acessos ao HashMap mas eu me pergunto se você também deve verificar se o seu generate_transaction_id () é o segmento de seguros ou se está se comportando de uma forma inesperada.

Você equals() substituído, mas não hashCode() em seus objetos de modelo? Como cerca de compareTo()? Se você obtém esses errado, coleções irão se comportar estranhamente, de fato.

Verifique Práticas de Java na é igual a () e compareTo () .

O que isso generate_transaction_id function () fazer? Se ele está gerando uma coisa GUID-como de 16 bits, você pode facilmente obter colisões de hash. Combinado com threading, você pode obter:

T1: transaction1.tran_no = generate_transaction_id();    => 1729
T2: transaction2.tran_no = generate_transaction_id();    => 1729
T1: transactions.put(transaction1.tran_no, transaction1); => map.put(1729, transaction1)
T2: transactions.put(transaction2.tran_no, transaction2); => map.put(1729, transaction2)
T1: int tran_no = transactions.get(1729);               => transaction2
T1: transactions.remove(transaction.tran_no);           => map.remove(1729)
T2: int tran_no = transactions.get(1729);               => null

Claro, isso só poderia ser uma solução se isso é para o melhor de seu conhecimento "parte não é verdade.

Então você sabe do HashMap não thread-safe. Tem certeza de que ele está sendo acessado por apenas um segmento? Afinal, falhas intermitentes uma frequência threading relacionados. Se não, você pode envolvê-lo com Collections.synchronizedMap() , assim:

Collections.synchronizedMap(transactions);

Você pode sempre apenas tentar para que você pode eliminar essa possibilidade.

Deve-se salientar que isso só envolve o mapa original com um com todos os métodos sincronizados. Você pode querer considerar o uso de um bloco sincronizado se o acesso estiver localizada.

Enfiar foi mencionado em A já algumas respostas, mas você já considerou a questão visibilidade para objetos utilizados por vários segmentos? É possível (e bastante comum) que se você colocar um objeto em uma coleção em um segmento, ele não será "publicado" a outros tópicos, a menos que você tenha sincronizado corretamente na coleção.

Threads e Locks

Sincronização e segurança do thread em Java

Como já foi observado você tem que saber se o HashMap é acessado por apenas uma linha, ou não. CollectionSpy é um novo perfil que permite que você descubra instantaneamente, para todos os recipientes, quantos threads executar quaisquer acessos. Consulte www.collectionspy.com para mais detalhes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top