2010-03-01 9 views
-2

Mon programme comporte un thread de serveur et des threads client distincts qui sont des connexions individuelles à d'autres serveurs. Donc, comment fonctionne mon programme est les threads du client font des demandes individuelles, et quand chacun d'eux, je incrémente la variable partagée iTimeStamp.Impossible d'obtenir la valeur de variable partagée dans des threads distincts

Cependant, j'ai besoin d'accéder à cette valeur de variable partagée via mon thread serveur, mais chaque fois que j'essaie, il n'obtient pas la valeur mise à jour, et la valeur iTimeStamp est toujours zéro.

Je viens de coller tout le code ci-dessous, j'apprécierais vraiment que quelqu'un puisse me dire ce qui me manque juste pour pouvoir accéder à la valeur iTimeStamp mise à jour. Maintenant, mon programme principal qui implémente plusieurs classes qui accèdent aux variables de la classe Global en tant que variables partagées.

class ServerConnect extends Thread { 

    Socket skt; 
    int iProcessId, iInProcessId; 
    int iOwnTimeStamp, iInTimeStamp; 
    ServerConnect scnt = null; 

    ObjectOutputStream myOutput; 
    ObjectInputStream myInput; 

    ServerConnect(){} 
    ServerConnect(Socket connection, int iProcessNo) { 
     this.skt = connection; 
     this.iProcessId = iProcessNo; 
    } 

    public void run() { 
     try { 

      //initialize the object "scnt" using the parameterized constructor 
      ServerConnect scnt = new ServerConnect(skt, iProcessId); 
      myInput = new ObjectInputStream(skt.getInputStream()); 

      while(true) { 
       try{ 

        Object buf = myInput.readObject(); 

        //if we got input, print it out and write a message back to the remote client... 
//******************************************************************************** 
//part where im trying to access the shared variable  
         //synchronized(Global.xlock){ 
        iOwnTimeStamp = Global.getInstance().iTimeStamp; 
             //} 
//*********************************************************************************** 

       }catch(ClassNotFoundException e) { 
        e.printStackTrace(); 
       } 
      } 
     } catch(IOException e) { 
      e.printStackTrace(); 
     } 
    } 

class Server extends Thread { 

    int iProcessId; 
    int iPortNo; 

    Server(){} 
    Server(int iPName, int iPortNumber){ 
     this.iProcessId = iPName; 
     this.iPortNo = iPortNumber; 
    } 

    public void run() { 
     try{ 
      //first create a socket & bind it to port 9999 
      ServerSocket myServerSocket = new ServerSocket(this.iPortNo); 
      while(true) { 
       //wait for an incoming connection 
       Socket skt = myServerSocket.accept(); 
       ServerConnect sc = new ServerConnect(skt, iProcessId); 
       Thread t = new Thread(sc);//Encapsulating each connection inot a class and running it as a separate Thread 

       t.start(); 
      } 
     }catch(IOException ex){ 
      ex.printStackTrace(); 
     } 
    } 
} 


class Client extends Thread{ 
    int iProcessId; 
    String sMessage; 
    Socket skt; 
    //int iNumReq=0; 

    ObjectOutputStream myOutput; 
    ObjectInputStream myInput; 

    //Constructor that accepts the processId, the corresponding socket and message if any 
    Client(int iPid, Socket s, String m) { 
     this.iProcessId = iPid; 
     this.skt = s; 
     this.sMessage = m; 
    } 

    public void run() { 
     try { 
      sleep((int)1*8000); 
     }catch(Exception e) {} 


     try { 
      //Creating input and output streams to transfer messages to the server 
      myOutput = new ObjectOutputStream(skt.getOutputStream()); 
      myInput = new ObjectInputStream(skt.getInputStream()); 

      //ive omitted the part where the client receives the reply from the server 

    //sendMessage is called to send messages from the client to the server it is connected to 
    void sendMessage(Object msg){ 
     if(msg!=null){ 
      try{ 
       myOutput.writeObject(msg); 
       myOutput.flush(); 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

public class BaseStaInstance extends Thread { 

    //variables for every BaseStation instance 
    //int iTimeStamp=0; 
    int iProcessId; 
    Client[] clientList; 
    private static BaseStaInstance bs = null; 
    Utility u = new Utility(); 

     //I have the readFile() function implemented here which I have left out 

    //setProcessId() 

    //setClientList() 

     //getClientList() 

    //getIpPort() 

    //The connSetUp is used to set up the initial connection between clients and servers 
    Client[] connSetUp(int iPid){ 
     //Broadcast to all processes other than itself 
     ArrayList sPortList = u.getPortList(iPid); 

     //making a consistency check to ensure the number of stations in the config file is equal to the number specified in the parameter file 
     if(sPortList.size()!=(Global.iParameter[1]-1)){ 
      Global.iParameter[1]=sPortList.size()+1; 
      System.out.println("Please note there was an inconsistency in the number of instances specified which was corrected as per the config file"); 
     } 

     //creating the connections from this basestation to the other basestation instances on their ports 
     Client[] clientList = new Client[Global.iParameter[1]-1]; 
     for(int i=0;i<Global.iParameter[1]-1;i++){ 
      String str = sPortList.get(i).toString(); 
      int iProcessToConnect = Integer.parseInt(str.substring(0,str.indexOf(","))); 
      str = str.substring(str.indexOf(",")+1); 
      String sMachineName = str.substring(0, str.indexOf(",")); 
      int iPortNo = Integer.parseInt(str.substring(str.indexOf(",")+1,str.length())); 
      try { 
       Socket skt = new Socket(sMachineName, iPortNo);   
       Client client = new Client(iProcessToConnect, skt, null); 
       client.start(); 
       clientList[i] = client; 
       try { 
        sleep((int)10000); 
       }catch(Exception e){} 
      }catch(Exception e){} 
     } 
     return clientList; 
    } 


    void broadcastReq(Object message){ 
     Client[] clientListValue = getClientList(); 
     for(int i=0;i<clientListValue.length;i++){ 
      Client client = clientListValue[i]; 
      client.sendMessage(message); 
     } 
    } 

    void genRequest(){ 
     //while(true){ 
      try{ 
       sleep((int)(new Random().nextInt(50))*100); //The broadcast is done on a random basis 
       //i has tried implementing the synchronized function but did not help 
       //synchronized(Global.xlock){ 
       //increment the time stamp on generating the request 
//******************************************************************************** 
//part where im incrementing the iTimeStamp variable. 
       Global.getInstance().iTimeStamp++; 
//******************************************************************************** 
       //} 

       bs.broadcastReq("Request-BaseStation,"+iProcessId+","+Global.getInstance().iTimeStamp); 

      }catch(Exception e){} 
     //} 
    } 

    public static void main(String args[]){ 
     bs = new BaseStaInstance(); 

     //read the program parameters file 
     bs.readFile(); 

     int iProcessId = Integer.parseInt(args[0]); 
     bs.setProcessId(iProcessId); 

     String sIpPort = bs.getIpPort(); 
     int iServ_port_no = Integer.parseInt(sIpPort.substring(sIpPort.indexOf(",")+1,sIpPort.length())); 

     System.out.println("The port number: "+iServ_port_no); 

     //Code to Debug--------- 
     //System.out.println("The Server Port No: "+iServ_port_no); 
     //---------------------- 

     Server serv = new Server(iProcessId, iServ_port_no); 
     serv.start(); 

     try { 
      sleep((int)10000); 
     }catch(Exception e){} 

     Client[] clientList = bs.connSetUp(iProcessId); 
     bs.setClientList(clientList); 

     bs.genRequest(); 

    } 
} 

est juste la partie que je l'ai mis en évidence avec ************ que j'ai besoin d'aide comprendre, j'ai omis certaines fonctions non liées juste pour éviter l'entassement.

Merci les gars à l'avance

+0

Veuillez formater correctement votre message, il est difficile de voir ce qui se passe ici. – Luhar

+0

Vous attendez-vous à ce que quelqu'un se rende à cette masse de code? Bonne chance. Publier un SSCCE (http://www.sscce.org) pour avoir une meilleure chance de bonnes réponses. –

+0

Je ne connais pas tout le monde, mais j'ai tendance à implémenter 'Runnable' au lieu d'étendre' Thread'. De cette façon, je peux avoir une véritable hiérarchie d'héritage pour mes classes threadées. – Powerlord

Répondre

2

Essayez de faire de iTimeStamp volatile, ou utiliser java.util.concurrent.atomic.AtomicInteger

+0

j'ai réussi à corriger le bug .... j'avais utilisé le mot-clé volatile, id utilisé synchronisé et tout ce que je puis a déclaré la variable iTimeStamp comme public static dans ma classe principale et y a accédé en utilisant le nom de classe dans les autres classes cela ne fonctionnait toujours pas j'ai réalisé que la méthode run() dans ma classe ServerConnect accédait correctement à la valeur, cependant l'autre fonction replyChoice qui a été appelé à partir de la classe ServerConnect et que j'ai omis du code ci-dessus n'a pas pu obtenir la valeur mise à jour et le bogue a été corrigé en transmettant simplement la valeur en paramètre à la fonction replyChoice –

2

Les variables individuelles partagées par plusieurs threads doivent être déclarés avec le mot-clé volatile. Cela garantit que toutes les écritures à cette variable par un thread sont immédiatement visibles à tous les autres threads. Sans cela, les threads peuvent avoir leur propre copie locale de la variable. Vous pouvez également utiliser l'une des classes du package java.util.concurrent.atomic, par exemple AtomicInteger.

+0

J'ai réussi à corriger le bogue. .. j'avais utilisé le mot-clé volatile, id utilisé synchronisé et tout puis déclaré la variable iTimeStamp comme public static dans ma classe principale et y accédé en utilisant le nom de la classe dans les autres classes il n'a toujours pas fonctionné je me suis rendu compte que la course() méthode dans ma classe ServerConnect accédait à la valeur correctement, mais l'autre fonction replyChoice qui a été appelé de la classe ServerConnect et que j'ai laissé à partir du code ci-dessus n'a pas pu obtenir la valeur mise à jour et le bogue a été corrigé la valeur comme un paramètre à la fonction replyChoice –

1

Dans le constructeur global, vous définissez gb = null. Dans getInstance(), vous renvoyez gb. Il n'y a aucun code posté qui définit jamais gb à une autre valeur. Cela se traduira par null pointeur exceptions.

Essayez de remplacer la déclaration au niveau global par

public static Global gb = new Global()
.

De même, vous devriez envisager de le définir en privé sur public - sauf si vous voulez que d'autres threads changent la valeur de gb sur vous.

+0

j'ai réussi à corriger le bug .... j'avais utilisé le mot-clé volatile, id utilisé synchronized et tout ce que j'ai déclaré la variable iTimeStamp comme public statique dans ma classe principale et y accédé en utilisant le nom de classe dans les autres classes, il ne fonctionnait toujours pas je me suis rendu compte que la course () méthode dans ma classe ServerConnect accédait à la valeur correctement, cependant l'autre fonction replyChoice qui était appelée de la classe ServerConnect et que j'ai omis du code ci-dessus n'a pas pu obtenir la valeur mise à jour et le bogue a été corrigé valeur en tant que paramètre de la fonction replyChoice –