Olá, estou com uma dúvida com relação ao método:
public ActionForward execute(ActionMapping map, ActionForm form, HttpServletRequest req, HttpServletResponse res){...}
do Struts.
Fiz alguns testes e percebi que o struts sempre usa o mesmo objeto para tratar as requisições. Isso me deixou com essa dúvida…
Pelo que pude notar tb o método execute não é synchronized, então como o Struts faz pra bloquear o acesso simultâneo e não corromper os dados?
É algum tipo de mecanismo interno?
Existe a possibilidade de corrupção dos dados?
Devo sincronizar o método execute()?
Grato.
Abs.
Paulo Gervasio
Ola Paulo,
No meu entendimento quando você seta sua action com scope resquest, a cada requisição feita para a action o struts faz uma nova instância da sua classe definida no struts.xml, portanto você não precisa se preocupar com synchronized.
Se você estiver mexendo com parametros do contexto do servlet você poderá ter os mesmos problemas da api do servlet, coisas como alterar parametros do ServletContext.
Por favor me corrija alguem se estiver errado
[quote]No meu entendimento quando você seta sua action com scope resquest, a cada requisição feita para a action o struts faz uma nova instância da sua classe definida no struts.xml, portanto você não precisa se preocupar com synchronized.
[/quote]
Então, eu fiz o teste, ele só chama o construtor uma vez…
Não tenho certeza…mas pode ser que ele trate igual um servlet trata suas requisições…
Quando você tem seu servlet lá MeuServlet, ele só chama o construtor uma vez, na verdade quem controla isso é o container, mas o que importa é que cada vez que você faz uma requisição é criado uma nova thread que chama o metodo que foi invocado no servlet, por exemplo doGet.
Por exemplo:
Tenho meu ServletA, e dois usuários U1 e U2.
Quando o container inicia o ServletA é construido e chama o metodo init();
Quando U1 faz uma requisição get é criado uma Thread 1 para ele com a chamada do metodo doGet do Servlet. Quando U2 faz uma requisição get ao mesmo tempo de U1 outra thread é criada com uma chamada para o método doGet.
Ou seja, apesar do construtor ser chamado uma unica vez você não se preocupa com o synchronized do metodo get.
Imagino que o struts funciona de maneira semelhante.
Ele nao bloqueia…
Dependerá de como fizer seu código…
Em primeira instancia não… mas pode ser necessário dependendo da sua funcionalidade… mas de qualquer maneira, o interessante é não sincronizar…
Se vc tiver que sincronizar o execute()… pode ser que sua aplicacao nao esteja muito bem organizada…
Olá rogelgarcia, como vai?
Então é possível haver dois acessos simultâneos ao método execute()?
Como devo proceder pra que isso não ocorra?
Não consegui visualizar uma maneira de desenvolver um código seguro sem usar o synchronized, você poderia me dar algum exemplo?
Grato.
Não teria problema duas pessoas acessarem o mesmo método ao mesmo tempo.
Imagine que o método execute, busque algumas informacoes no banco de dados… e depois coloque no escopo de requisicao:
//pseudocodigo
String execute(){
List<Funcionario> funcionarios = daoFuncionario.listAll();
request.setAttribute("funcionarios", funcionarios);
}
Nao teria problema duas pessoas acessarem ao mesmo tempo… as variaveis locais do método não sao compartilhadas… e o request tb nao…
Entendeu?
Estude sobre threads um pouco para vc pode compreender isso…
Então, isso que tá me deixando confuso, por exemplo.
- Há dois acessos praticamente simultâneos no método:
[code]execute(HttpServletRequest req,otherArgs…){
//
int i=0;
for (i=0 ;i < 1000; i++) {
// muitas tarefas executadas
}
// linha 8
// countVisitor é inserido o contador i
req.setAttribute(“countVisitor”, i);
}[/code]
Vamos supor a primeira thread tenha acabado de executar o for, (‘linha 8’) e a segunda thread acesse o método e atribua “i=0”
A primeira thread receberá o valor de 0 e o atribuirá a countVisitor, enquanto deveria receber o valor correspondente ao iterador do loop…
Mesmo se ela receber parâmetros diferentes, continua sendo o mesmo método…
Até mesmo no seu exemplo:
1. //pseudocodigo
2. String execute(){
3. List<Funcionario> funcionarios = daoFuncionario.listAll();
4. request.setAttribute("funcionarios", funcionarios);
5. }
Se no momento em que a primeira thread for atribuir o valor a variável e a segunda thread fizer uma nova requisição, poderia ocorrer até mesmo um NullPointerException, ou na melhor das hipóteses a lista vir incompleta…
Não acha?
Grato.
Paulo Gervasio.
Não… num acontece isso nao…
As variaveis locais… as que existem dentro dos métodos… não sao compartilhadas entre as threads…
Entao vc pode fazer qualquer coisa dentro do método… usando variaveis locais… que nao vai dar problema…
A threadA vai ter uma variavel i… e a threadB vai ter outra variavel i…
Daria problema se fosse um atributo… aí uma influenciaria na outra… então NÀO USE ATRIBUTOS NAS ACTIONS… hehehe
Ahhhh, agora entendi!
Vlw
Abs.