Dúvida sobre thread em site feito em java

4 respostas
Dafne

Olá a todos.

Eu entendo o funcionamento de threads e métodos atômicos (synchronized). Mas tenho dúvida quando o assunto é site desenvolvido em java, pois em nenhum momento criamos threads na mão. Como funcionam as threads nesse caso? Cada janela ou aba aberta no navegador é uma thread? Então cada usuário(cliente) pode ter várias threads rodando se abrir várias janelas/abas?

Por exemplo. Tenho um e-commerce feito em java (com struts). Quando um cliente compra um produto, tenho que reduzir a quantidade no estoque. Vamos supor que tenho 4 canetas disponíveis no estoque. O cliente A coloca 3 canetas no carrinho de compras, o cliente B coloca 2. O cliente A vai finalizar o pagamento. Entra no método que primeiro verifica se realmente existem 3 canetas no estoque, e existem. Nesse momento ele dorme (se for uma thread). Mas então o cliente B decide finalizar a compra também e acessa o mesmo método, que verifica se existem 2 canetas no estoque, e existem, porque o cliente A dormiu antes de subtrair as 3 canetas do estoque. O cliente B dorme. O cliente A acorda e finaliza a transição, retirando as 3 canetas do estoque. Nesse momento o cliente B também acorda e retira mais 2 canetas do estoque, que ficará com -1, pois só havia 4 canetas e foram retiradas 5.

Se for isso mesmo, então o certo é eu criar um método synchonized na Action que confere o estoque e reduz a quantidade, certo? E ainda mais, esse método tem que ser static? Pois se não for static, como a Action do Struts é tratada como um novo objeto a cada requisição, o método synchonized não será tratado como atômico, certo?

4 Respostas

E

se me lembro bem, cada request é uma thread. O container implementa um pool de threads e se todas as threads estão lotadas entra em uma “lista de espera”.

Agora, a segunda parte, pelo que me lembro, se você usa um framework JPA, os objetos são synchronized, e quando algum objeto com algum ID determinado está em transação, as outras threads não podem acessá-lo. Isso solucionaria o problema das threads. (considere que os frameworks JPA verificam se existe algum objeto na memória com o id que você está buscando)

Mas não lembro se era exatamente assim que funciona, vamos esperar outra pessoa responder.

Dafne

Obrigada evefuji, você me deu uma luz. Estou usando o Hibernate. Vou dar uma lida na documentação pra ver se acho alguma coisa. Se achar posto aqui.

maior_abandonado

Dafne:
Olá a todos.

Eu entendo o funcionamento de threads e métodos atômicos (synchronized). Mas tenho dúvida quando o assunto é site desenvolvido em java, pois em nenhum momento criamos threads na mão. Como funcionam as threads nesse caso? Cada janela ou aba aberta no navegador é uma thread? Então cada usuário(cliente) pode ter várias threads rodando se abrir várias janelas/abas?

Por exemplo. Tenho um e-commerce feito em java (com struts). Quando um cliente compra um produto, tenho que reduzir a quantidade no estoque. Vamos supor que tenho 4 canetas disponíveis no estoque. O cliente A coloca 3 canetas no carrinho de compras, o cliente B coloca 2. O cliente A vai finalizar o pagamento. Entra no método que primeiro verifica se realmente existem 3 canetas no estoque, e existem. Nesse momento ele dorme (se for uma thread). Mas então o cliente B decide finalizar a compra também e acessa o mesmo método, que verifica se existem 2 canetas no estoque, e existem, porque o cliente A dormiu antes de subtrair as 3 canetas do estoque. O cliente B dorme. O cliente A acorda e finaliza a transição, retirando as 3 canetas do estoque. Nesse momento o cliente B também acorda e retira mais 2 canetas do estoque, que ficará com -1, pois só havia 4 canetas e foram retiradas 5.

Se for isso mesmo, então o certo é eu criar um método synchonized na Action que confere o estoque e reduz a quantidade, certo? E ainda mais, esse método tem que ser static? Pois se não for static, como a Action do Struts é tratada como um novo objeto a cada requisição, o método synchonized não será tratado como atômico, certo?

essa parte de thread é abstraída pelo servidor web e quanto a isso você não deveria precisar se preocupar, ele responde cada requisição simultânea com uma thread diferente mas acredito que ele reaproveite threads (talvez use recursos de pool de threads como os do pacote java.util.concurrent), da para ver isso logando o nome da thread no seu log(%t no pattern do log4j), mas nem é ai que você tem que se preocupar quando for fazer isso. Quanto a essa regra de negócio de reservar o produto no estoque ai você tem que ver como você vai fazer isso e você mesmo fazer, por exemplo, se você quiser que a pessoa tenha o produto reservado ao coloca-lo em um carrinho de compras, você pode dar um lock no banco de dados na linha do estoque com este produto, ou pode setar alguma coluna com um flag para reservado, ou como você preferir. Se você não quiser reservar o produto, poderá verificar se tem no estoque tanto quando permite que o cliente insira no carrinho de compras quanto quando ele finalizar a compra…

Dafne

Obrigado a todos por iluminarem minhas idéias. Pesquisei bastante na documentação do Hibernate. Pode-se trabalhar com “versão de dado”. Ou seja, coloca-se um campo int com a anotação @Version na entity. A cada atualização do dado (linha da tabela), a coluna version será incrementada.

Com isso, caso duas pessoas ou mais estejam visualizando um dado do banco através de um formulário, e a primeira pessoa atualiza o dado, a segunda pessoa estará visualizando o dado antigo, e ao tentar atualizá-lo o Hibernate lançará uma exceção.

Isso é bem explicado nesses links.
http://vimeo.com/18800828
http://www.ufpi.br/subsiteFiles/pasn/arquivos/files/hibernate.pdf
http://docs.jboss.org/hibernate/core/3.6/reference/pt-BR/html_single/#transactions

Mas no meu caso o estoque não será atualizado por formulário e sim quando o usuário finaliza a compra. O código gera o pedido e retira os produtos do estoque.

Então preferi criar um método que confere se existem os produtos no estoque, bem como a quantidade, e reduz o estoque fechando o pedido. Esse método será static, pois a cada requisição (thread) uma nova instância da Action será criada (estou trabalhando com Struts), e dessa forma duas requisições conseguiriam entrar nesse método ao mesmo tempo pois estariam trabalhando com diferentes instâncias da Action chamada.

Não quis retirar do estoque no momento me que o cliente coloca o produto no carrinho pois nem sempre ele finaliza a compra. Então se no momento em que ele vai fechar a compra, outro cliente comprou o último produto do estoque, será retornada uma mensagem dizendo que aquele produto não consta mais no estoque.

Por isso eu precisava entender como o sistema gera as threads.

Valeu.

Criado 19 de dezembro de 2011
Ultima resposta 21 de dez. de 2011
Respostas 4
Participantes 3