无法在单独的线程中获取共享变量值

发布于 2024-08-23 03:16:56 字数 8135 浏览 3 评论 0原文

我的程序有一个服务器线程和单独的客户端线程,它们是与其他服务器的单独连接。因此,我的程序的工作原理是客户端线程发出单独的请求,当每个请求如此时,我都会增加共享变量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;
}

现在,我的主程序实现了几个类,这些类将 Global 类中的变量作为共享变量访问。

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

    }
}

这只是我用 ************ 突出显示的部分,我需要帮助来弄清楚,我省略了一些不相关的功能只是为了避免拥挤。

提前谢谢大家

My program has a server thread and separate client threads that are individual connections to other servers. So how my program works is the client threads make individual requests, and when each of them so, I increment the shared variable iTimeStamp.

However, I need to access this shared variable value through my Server thread, but whenever I do try that it doesn't get the updated value, and the value of iTimeStamp that gets accessed is always zero.

I've just pasted the entire code below, I'd really appreciate if someone could tell me what I'm missing just so I can access the updated iTimeStamp value.

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;
}

Now, my main program that implements several classes that access the variables in the Global class as shared variables.

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

    }
}

Its just the part that I've highlighted with ************ that I need help with figuring out, I've omitted some non related functions just to avoid crowding.

Thanks guys in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

煮酒 2024-08-30 03:16:56

尝试使 iTimeStamp 易失性,或使用 java.util.concurrent.atomic.AtomicInteger

Try making iTimeStamp volatile, or use java.util.concurrent.atomic.AtomicInteger

吐个泡泡 2024-08-30 03:16:56

多个线程共享的单个变量应使用 volatile 关键字声明。这可确保一个线程对该变量的任何写入都立即对所有其他线程可见。如果没有这个,线程可能会有自己的线程本地变量副本。您可能还想考虑使用 java.util.concurrent.atomic 包中的类之一,例如 AtomicInteger。

Single variables shared by multiple threads should be declared with the volatile keyword. This ensures that any writes to that variable by one thread are immediately visible to all other threads. Without this, threads may have their own thread-local copy of the variable. You might also want to look into using one of the classes from the java.util.concurrent.atomic package, such as AtomicInteger.

莳間冲淡了誓言ζ 2024-08-30 03:16:56

在 global 的构造函数中,设置 gb = null。在 getInstance() 中,您返回 gb。没有发布任何代码将 gb 设置为任何其他值。这将导致空指针异常

尝试将 global 内的声明更改为

public static Global gb = new Global()

.

另外,您应该考虑将其设置为私有而不是公共 - 除非您希望其他线程更改您的 gb 值。

In global's constructor, you set gb = null. In getInstance() you return gb. There is no code posted that ever sets gb to any other value. This will result in null pointer exceptions.

Try changing the declaration inside global to

public static Global gb = new Global()

.

Also, you should consider setting it to private instaead of public - unless you want other threads to change the value of gb on you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文