2010-09-28 11 views
1

Ok, donc j'ai un test client/serveur en cours, et je passe l'entier playerID à un fil où il donne la valeur int à un simple objet de joueur, que incréments playerId par 1.Nombre entier n'augmentera pas?

public static void main(String[] args) throws IOException { 

     Vector<Player> player = new Vector<Player>(); 

     SlickServer ss = new SlickServer(); 
     ss.setVisible(true); 

     ServerSocket serverSocket = new ServerSocket(4444); 
     boolean listening = true; 

     Integer playerID = new Integer(0); 

     while(listening){ 
      ss.textArea.append("Waiting to connect with player: " + playerID.intValue() + "\n"); 
      new ClientThread(serverSocket.accept(), player, playerID, ss.textArea).start(); 
      ss.textArea.append("Waiting to connect with player: " + playerID.intValue() + "\n"); 
     } 

     serverSocket.close(); 
     System.exit(0); 
    } 

et ici où il incrémente dans le fil:

public ClientThread(Socket acceptedSocket, Vector<Player> players, Integer playerID, JTextArea textArea){ 
     super("ClientThread"); 
     this.acceptedSocket = acceptedSocket; 
     this.players = players; 
     players.add(new Player(50,50, playerID.intValue())); 

     if(players != null) 
      System.out.println("Not Null: " + players.size()); 

     boolean b = false; 
     for(int i = 0; i < players.size(); i++){ 
      if(!b){ 
       if(players.get(i).id == playerID){ 
        me = players.get(i); 
        b = true; 
       } 
      } 
     } 

     playerID = new Integer(playerID.intValue() + 1); 
     this.textArea = textArea; 
    } 
+3

lecture http://stackoverflow.com/questions/40480/is-java-pass-by-reference peut vous donner une idée de la raison pour laquelle cela ne fais ce que tu attends. –

+1

Si vous voulez en savoir un peu plus sur le partage de données entre les threads, je recommanderais Java Concurrency in Practice. En bref, si vous ne concevez pas explicitement des variables pour le partage, vous ne savez jamais ce que vous obtenez. – extraneon

Répondre

7

new Integer crée une toute nouvelle Integer exemple dans la méthode de thread client qui ne sont pas disponibles à l'appelant. Toutefois, vous devez prendre en compte la synchronisation entre l'unité d'exécution principale et l'unité d'exécution client. Ceci peut être réalisé à l'aide synchronized déclarations pour les objets triviaux ou classes telles que java.util.concurrent.atomic.AtomicInteger pour les entiers comme suit:

AtomicInteger playerID = new AtomicInteger(0); 
while (listening) { 
    ss.textArea.append("Waiting to connect with player: " + playerID.get() + "\n"); 
    new ClientThread(serverSocket.accept(), player, playerID, ss.textArea).start(); 
    ss.textArea.append("Waiting to connect with player: " + playerID.get() + "\n"); 
} 

class ClientThread { 
    public ClientThread(Socket acceptedSocket, Vector<Player> players, AtomicInteger playerID, JTextArea textArea) { 
    // etc. 
    playerID.incrementAndGet(); 
    // etc. 
    } 
} 

Vous devez réfléchir à la façon de partager des données entre les threads d'exécution simultanément. Cela s'applique également aux arguments Vector<Player> et JTextArea. Vous devez envelopper les accès aux objets players et textArea en utilisant les instructions synchronize selon le cas.

+0

'ClientThread' ne devrait pas être responsable de l'incrémentation de l'ID, point. – ColinD

+0

Parce que ce n'est pas la solution à son problème qu'il devrait utiliser. Évidemment, il a besoin de connaître le fonctionnement de Java, mais dans ce cas, la racine de son problème est qu'il apprend comment incrémenter son ID de joueur dans le mauvais sens et mettre cette responsabilité au mauvais endroit. – ColinD

+1

Je ne comprends vraiment pas pourquoi vous faites toutes ces choses de synchronisation de données partagées quand il s'agit simplement d'incrémenter à l'endroit où la variable est définie. De plus, vous n'avez pas besoin de synchronisation si elle n'est incrémentée que dans le constructeur, qui est appelé sur un seul thread. De plus, la synchronisation n'aiderait pas même si elle était nécessaire puisque vous ne pouvez pas faire un incrément atomique en utilisant votre 'SharedData' ... un' AtomicInteger' serait mieux. – ColinD

0

Essayez d'utiliser IntHolder si vous en avez besoin.

+2

AtomicInteger est conçu uniquement pour ces cas. – extraneon

2

Incrémenter l'ID du lecteur dans main après avoir créé le ClientThread.

Le thread client ne doit pas être responsable de l'incrémentation de l'ID du lecteur. C'est la responsabilité de main, qui est la création de threads de client et de leur donner leurs ID.

0

Si vous souhaitez manipuler l'entier dans la méthode, vous devez l'encapsuler dans un objet.

Lire cet article pour une meilleure compréhension http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

+2

Java ne transmet pas les objets par référence. Il passe les références par valeur. Il y a un monde de différence. – dty

+0

Merci @dty, j'ai supprimé les détails erronés. –