Pergunta

Estou usando a seguinte abordagem de spinlock:

while(!hasPerformedAction()){
    //wait for the user to perform the action
    //can add timer here too
}

setHasPerformedAction(false);

return getActionPerfomed();

Isso basicamente espera que um usuário execute uma ação e depois a retorne. Atualmente, algo solicita uma resposta do usuário antes de continuar, é por isso que espero até que a entrada seja recebida. No entanto, eu queria saber se isso é ineficiente e se estamos esperando por um tempo (ou seja, <= 30 segundos), isso diminuirá o PC que está executando este aplicativo. Existem outras alternativas usando essa abordagem, isto é, semáforos, se sim, qual é a sintaxe?

Obrigado,

Aly

Foi útil?

Solução

De fato, isso não é apenas ineficiente, mas também é garantido funcionar, pois não há uma borda "antes" no código que você está mostrando. Para criar um acontece antes da borda você precisa fazer um de:

  1. Acesse uma variável volátil
  2. Sincronizar em um recurso compartilhado
  3. Use um bloqueio de utilitários simultâneos.

Como mencionado em outro comentário, o mais fácil A solução é simplesmente garantir que sua bandeira seja uma variável volátil e simplesmente jogue um sono curto no seu loop.

No entanto, a melhor coisa a fazer seria sincronizar/esperar/notificar em uma variável compartilhada.

Os métodos que você precisa ler são esperar e notificar. Para uma descrição melhor sobre como usá -los, leia Este artigo. Um exemplo de código de código é mostrado abaixo;

Tópico 1

Object shared = new Object();
startThread2(shared);
synchronized (shared) {
  while (taskNotDone())
    shared.wait();
}

Tópico 2

// shared was saved at the start of the thread
// do some stuff
markTaskAsDone();
synchronized (shared) {
  shared.notify();
}

Outras dicas

O que você escreveu é chamado de loop ocupado, o que você nunca deve fazer.

Você pode continuar fazendo isso, mas pelo menos dormir um pouco para não estar ocupado em loop, o que ainda não seria tão bom:

while( !hasPerformedAction() ) {
    (sleep a bit here)
}

Outra maneira de fazê -lo seria para envolver as ações do usuário em uma fila de bloqueio: então você pode simplesmente estar usando um fila.take E a implementação da fila cuidaria do problema para você.

E outra maneira seria usar um retorno de chamada para ser notificado das ações do usuário.

Os tutoriais do Java têm uma boa lição sobre a simultaneidade em Java:

http://java.sun.com/docs/books/tutorial/essential/concurrency/

Se você vai modificar a interface do usuário de outro tópico, você deve se lembrar de fazer:

SwingUtils.invokeLater(actionToInvoke);

Há um GUI Em suas tags, então assumirei que a ação é feita na GUI.

A maneira "recomendada" de fazer esse tipo de coisa é para o tópico principal se colocar para dormir (talvez usando wait()) e para a ação da GUI para notify() De volta à vigília, uma vez que a ação for realizada.

Existem algumas aulas para isso em java.util.concurrent.locks. Dê uma olhada na aula LockSupport

Atenciosamente Mike

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