无法在单独的线程中获取共享变量值
我的程序有一个服务器线程和单独的客户端线程,它们是与其他服务器的单独连接。因此,我的程序的工作原理是客户端线程发出单独的请求,当每个请求如此时,我都会增加共享变量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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尝试使 iTimeStamp 易失性,或使用 java.util.concurrent.atomic.AtomicInteger
Try making iTimeStamp
volatile
, or usejava.util.concurrent.atomic.AtomicInteger
多个线程共享的单个变量应使用 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 thejava.util.concurrent.atomic
package, such asAtomicInteger
.在 global 的构造函数中,设置
gb = null
。在 getInstance() 中,您返回gb
。没有发布任何代码将 gb 设置为任何其他值。这将导致空指针异常。尝试将 global 内的声明更改为
.
另外,您应该考虑将其设置为私有而不是公共 - 除非您希望其他线程更改您的 gb 值。
In global's constructor, you set
gb = null
. In getInstance() you returngb
. 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
.
Also, you should consider setting it to private instaead of public - unless you want other threads to change the value of gb on you.