2010-03-01 45 views
-2

我的程序有一個服務器線程和單獨的客戶端線程,這些線程是與其他服務器的單獨連接。所以我的程序如何工作是客戶端線程發出個別請求,並且當他們每個人都這樣,我增加共享變量iTimeStamp無法在單獨的線程中獲取共享變量值

但是,我需要通過我的服務器線程訪問這個共享變量值,但每當我嘗試它不會獲得更新的值,並且iTimeStamp被訪問的值始終爲零。

我剛剛粘貼了下面的整個代碼,我真的很感激,如果有人能告訴我我什麼都不知道,所以我可以訪問更新的iTimeStamp值。

import java.util.Vector; 
import java.lang.*; 

public class Global { 

public static int[] iParameter = new int[8];  

public static Global gb = null; 

public static int iTimeStamp; 

public static Global getInstance(){ 
    return gb; 
} 

現在,我的主要程序,實現了訪問全局類作爲共享變量的變量幾類。

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(); 

    } 
} 

它只是一部分,我已經與************,我需要搞清楚幫助強調,我省略了一些不相關的功能,只是爲了避免擁擠。提前

謝謝你們

+0

請格式化您的文章,它很難看到這裏發生了什麼。 – Luhar 2010-03-01 08:24:08

+0

你是否期望任何人去參與那些大量的代碼?祝你好運。發佈SSCCE(http://www.sscce.org)以獲得更好的答案。 – 2010-03-01 21:22:52

+0

我不知道其他人,但我傾向於實現'Runnable'而不是擴展'Thread'。這樣,我可以爲我的線程類創建一個真正的繼承層次結構。 – Powerlord 2010-03-01 21:32:48

回答

2

嘗試使iTimeStamp volatile,或者使用多個線程共享java.util.concurrent.atomic.AtomicInteger

+0

我設法修復了這個錯誤....我使用了volatile關鍵字,id使用了synchronized,在我的主類中將變量iTimeStamp聲明爲公共靜態,並在其他類中使用類名稱訪問它,但仍然無法工作,我意識到我的ServerConnect類中的run()方法正確訪問該值,但其他函數replyChoice從ServerConnect類被調用,而我從上面的代碼遺漏了無法獲得更新的價值,並通過將值作爲參數傳遞給replyChoice函數修復了錯誤 – 2010-03-02 16:36:48

2

單變量應與volatile關鍵字來聲明。這確保了一個線程對該變量的任何寫入都對所有其他線程立即可見。沒有這個,線程可能擁有自己的線程局部變量副本。您可能還想使用java.util.concurrent.atomic程序包中的某個類進行研究,如AtomicInteger

+0

我設法修復了這個bug。 .. 我曾使用volatile關鍵字,id使用同步和一切 我然後在我的主類中聲明變量iTimeStamp爲公共靜態,並在其他類中使用類名訪問它 它仍然沒有工作 我意識到運行()方法正確地訪問該值,但從ServerConnect類中調用的另一個函數replyChoice,以及我從上面的代碼中刪除的函數無法獲取更新後的值,並且僅通過傳遞該值作爲replyChoice函數的參數 – 2010-03-02 16:36:24

1

在全球的構造函數中,您設置了gb = null。在getInstance()中,您返回gb。沒有發佈的代碼將gb設置爲任何其他值。這將導致空指針異常

嘗試將全局內的聲明更改爲

public static Global gb = new Global()
。另外,你應該考慮把它設置爲private的私人instaead - 除非你想讓其他線程改變你的gb值。

+0

我設法修復了這個錯誤....我使用了volatile關鍵字,id使用了synchronized,然後我將所有變量iTimeStamp聲明爲公共靜態在我的主類中,並使用在其他類中的類名稱它仍然沒有工作我意識到,運行( )方法正確地訪問該值,但從ServerConnect類中調用的另一個函數replyChoice,以及我從上面的代碼中刪除的函數無法獲取更新後的值,並且僅通過了值作爲replyChoice函數的參數 – 2010-03-02 16:37:11