Pergunta

Estou escrevendo uma simulação de bananagramas por diversão. Quero usar a simultaneidade, mas não tenho muita certeza de como.

Eu tenho um método principal em um Game classe. Cada um dos fios do jogador trabalha para uma solução. Em certos momentos, um jogador vai "descascar". Durante esta operação, todo jogador recebe um novo ladrilho. Um dos fios do jogador deve notificar o Game fio.

O pseudocódigo seria algo assim:

while (no player has reported they are finished) {
      if (player reports it is time to peel) {
           everyone peel 
      }
      everyone work towards completion of puzzle
}

Como posso implementar isso em Java? (Não estou necessariamente procurando soluções totalmente desenvolvidas, apenas me indique na direção certa.) Como quero lidar com a notificação entre objetos?

Esclarecer: Este não é um jogo de interação do usuário. Eu só quero tentar algoritmos diferentes para ver o que pode resolver o problema mais rápido. Se alguma coisa, o "jogo" estaria escrevendo um algoritmo e ligando -o para ver como ele funciona.

Foi útil?

Solução

Dependendo exatamente de qual é o seu processo, talvez você não precise fazer um threading (o que, confie em mim, é algo que você prefere evitar, se possível, por mais legal e divertido que as crianças grandes façam ser).

Uma maneira de abordar o problema é configurar uma fila de eventos.

no pseudocódigo

 enum EVENTTYPES = {PEEL=0, WORK=1};
 struct Event = {
     int eventType;
     int* data;
 }

 filoQueue eventQueue;

 array sQuidPlayers = [new Squid(), new Squid(), new Squid()];
 void eventLoop () {
      int player;
      for each player in sQuidPlayers {
          eventQueue.push(new Event(EVENTTYPES.WORK, player.id));
      }

      for each event in eventQueue {
           game.doEvent(event)
      }

 }

Então, aqui você executa o loop do evento 25 vezes, 30 vezes ou 60 vezes por segundo, qualquer taxa de quadro que deseja operar. Você usa um cronômetro para isso (tenho certeza de que há um em java em algum lugar)

Em seguida, o Doevent tentará procurar algum método de resposta na instância do player coordendo. O método de trabalho na classe Squid fará uma pequena parcela de trabalho e depois parará, esperando a próxima vez no loop. Cada lula na matriz é sua vez para fazer seu pequeno trabalho. O método de trabalho, por sua vez, pode colocar um evento de casca na fila de eventos. Nesse ponto, da próxima vez no loop, algum método coortado de casca poderá ser chamado. Talvez em alguma aula de jogo central, com o ID do jogador que originou o evento Peel. Você coloca a lógica de como despachar esses eventos no método doevent lá. O Doevent, por sua vez, pode passar em um objeto para cada receptor de evento, para que o receptor possa colocar seus próprios objetos de evento na fila para ser executado na próxima vez em torno do loop. (Como alternativa, o loop "para cada evento" é executado até que o EventQueue esteja vazio, e isso inclui novos eventos que acabam de ser adicionados por chamadas anteriores ao Doevent, para que um novo evento possa ser chamado imediatamente em vez de esperar pelo próximo quadro de animação)

O truque é descobrir como dividir seu trabalho de longa data em uma pequena parcela do trabalho, descobrir como salvar os resultados desse trabalho e pegue -o mais tarde, onde você parou na próxima vez que o método de trabalho for chamado. Se todos os jogadores forem bem comportados, todos podem compartilhar um tópico sem ficar presos.

Se você vai seguir o caminho encadeado, os problemas sobre quem podem acessar o pedaço de memória e quando ficam um pouco mais complicados.

Outras dicas

Este seria um bom lugar para usar um Barreira cíclica.

Essencialmente, uma barreira cíclica permite que os threads funcionem e depois que todos os threads esperem até que todos cheguem ao mesmo ponto; em seguida, cada rosca inicia novamente.

Portanto, você pode fazer com que cada jogador descasque e depois ligue para CyclicBarrier.await (). Todos os threads esperarão até que cada um chegue a esse ponto. O que parece ser o que você quer.

(Além disso, você obviamente não precisa de simultaneidade para isso :)

O padrão do observador pode ser apropriado. Todo mundo se registra no tópico principal para receber notificações sobre eventos de casca. Quando uma pessoa relata que é hora de descascar, ele notifica o tópico principal, que por sua vez notifica todos os threads registrados. A notificação pode ser feita através de uma variável local local (cada thread de jogador tem o seu próprio) definido pelo encadeamento principal por meio de uma chamada de método e verificado pelo thread do jogador em cada iteração do loop do jogo.

EDIT: Aqui está um link para um artigo que aprofunda mais a implementação do padrão de observador de maneira multithread em Java. http://www.javaworld.com/jw-03-1999/jw-03-oolbox.html

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