我的程序有一个服务器线程和单独的客户端线程,它们是与其他服务器的单独连接。所以我的程序如何工作是客户端线程发出单独的请求,当它们每个都这样时,我增加共享变量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();
}
}
它只是我用************
突出显示的部分,我需要帮助解决问题,为了避免拥挤,我省略了一些非相关函数。
提前谢谢你们
答案 0 :(得分:2)
尝试制作iTimeStamp volatile
,或使用java.util.concurrent.atomic.AtomicInteger
答案 1 :(得分:2)
多个线程共享的单个变量应使用volatile
关键字声明。这可确保一个线程对该变量的任何写入对所有其他线程立即可见。如果没有这个,线程可能有自己的变量的线程局部副本。您可能还希望使用java.util.concurrent.atomic
包中的某个类,例如AtomicInteger
。
答案 2 :(得分:1)
在global的构造函数中,设置gb = null
。在getInstance()中,您将返回gb
。没有发布任何代码将gb设置为任何其他值。这将导致空指针异常。
尝试将全局内部的声明更改为
public static Global gb = new Global()。
此外,您应该考虑将其设置为私有instaead公共 - 除非您希望其他线程更改您的gb值。