I have a runnable class "TemperatureSensor" which is periodically adding a new randomized floating point value to an array list TemperatureList as an object Temperature. The last added object in the array (index 0) is then sent from RMI client to RMI server - this happens without problems.
However, when I click a button on GUI to display the size of this object array, I always get a 0. If I print out the size of the array from RMI client class, it shows a correct size.
My question is, how do I access the same array from multiple classes correctly?
Here is the UML:
import java.text.DecimalFormat;
import java.util.Random;
public class TemperatureSensor implements Runnable
{
private int waitingTime;
private Model model;
public TemperatureSensor(Model model, int waitingTime)
{
this.model = model;
this.waitingTime = waitingTime;
}
@Override
public void run()
{
float temperature = 25.0f;
while(true)
{
temperature = measureTemperature(temperature);
model.addTemperatureData(temperature);
System.out.println("Sending: " + temperature);
waiting();
}
}
private float measureTemperature(float temperature)
{
Random rand = new Random();
float minTempFloat = 0.1f;
float maxTempFloat = 0.2f;
int incrementSwitch = rand.nextInt(3-0) + 0;
if (incrementSwitch == 0)
{
temperature += minTempFloat + rand.nextFloat() * (maxTempFloat - minTempFloat);
}
else if(incrementSwitch == 1)
{
//Do nothing
}
else if (incrementSwitch == 2)
{
temperature -= minTempFloat + rand.nextFloat() * (maxTempFloat -
minTempFloat);
}
return temperature;
}
private void waiting()
{
try
{
Thread.sleep(waitingTime);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
Model:
public interface Model
{
public void addTemperatureData(float value);
public Temperature getLatestTemperatureData();
public int getTempListSize();
}
ModelManager:
public class ModelManager implements Model
{
private TemperatureList temperatureList;
public ModelManager()
{
temperatureList = new TemperatureList();
}
@Override
public void addTemperatureData(float value)
{
Temperature temperature = new Temperature(value);
//this.temperatureList.clearTemperatureDataList();
this.temperatureList.addTemperatureDataToList(temperature);
}
@Override
public Temperature getLatestTemperatureData()
{
return temperatureList.getLatestTemperatureDataFromList();
}
@Override
public int getTempListSize()
{
return temperatureList.size();
}
}
RMIsensorClient:
import java.rmi.Naming;
import java.rmi.RemoteException;
public class RMIsensorClient
{
private RMIserverInterface serverInterface;
private static Model model = new ModelManager();
public static void main(String[] args) throws RemoteException, InterruptedException
{
TemperatureSensor tempSensor = new TemperatureSensor(model, 5000);
Thread tempThread = new Thread(tempSensor, "TempSensor");
tempThread.start();
RMIsensorClient sensorClient = new RMIsensorClient();
}
public RMIsensorClient() throws RemoteException
{
super();
try
{
serverInterface = (RMIserverInterface) Naming.lookup("rmi://localhost:1099/rmiServer");
while(true)
{
serverInterface.getTemperature(model.getLatestTemperatureData());
System.out.println(model.getTempListSize());
Thread.sleep(5000);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Controler:
public class Controller
{
private static Model model;
public Controller ()
{
this.model = new ModelManager();
}
public int getNumberOfListElements()
{
return model.getTempListSize();
}
}
GUI:
public class GUItemperatureController implements Initializable
{
private Controller controller = new Controller();
@FXML
private Label tlTemperature;
@FXML
private Pane mainPane;
@FXML
private TextField tfTemperature;
@FXML
private Button btnUpdate;
@Override
public void initialize(URL arg0, ResourceBundle arg1)
{
tfTemperature.setEditable(false);
}
@FXML
void showArraySize(ActionEvent event)
{
tfTemperature.setText(Integer.toString(controller.getNumberOfListElements()));
}
}
TemperatureList:
import java.io.Serializable;
import java.util.ArrayList;
public class TemperatureList implements Serializable
{
private ArrayList<Temperature> temperatureList;
public TemperatureList()
{
this.temperatureList = new ArrayList<>();
}
public void addTemperatureDataToList(Temperature temperature)
{
temperatureList.add(0,temperature);
}
public Temperature getLatestTemperatureDataFromList()
{
return this.temperatureList.get(0);
}
public void clearTemperatureDataList()
{
temperatureList.clear();
}
public int size()
{
return temperatureList.size();
}
}
Here is where I launch the GUI:
import java.rmi.RemoteException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class userMain extends Application
{
public FXMLLoader loader;
public static void main(String[] args)
{
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception
{
loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML/FXMLtemperature.fxml"));
loader.setController(new GUItemperatureController());
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setTitle("GEMS - Test");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Your problem is not about classes.
You run two separate applications. One runs your RMIsensorClient
and one runs your GUI
. They know nothing about each other, your RMIsensorClient
and your Controller
have their own separate instances of ModelManager
and you have no code anywhere that would share any data between them.
You need to make the data you want to show in your GUI accessible somehow.
One solution could be to use a network interface for that. Create two different ModelManager
s, one that opens and listens to a ServerSocket , and one that uses a Socket in getLatestTemperatureData()
to connect to the other one.
Use the former in your RMIsensorClient
and the latter in your GUI
's Controller
.
Research networking in Java.
This is a very crude solution, but there are plenty of great tutorials for networking and sharing data between multiple Java applications.
You haven't included your TemperatureList
implementation, but if as you say it's an ArrayList
it's likely you're not properly synchronizing access across threads . It's imperative that you properly synchronize cross-thread work otherwise you'll wind up with some sort of undefined behavior, such as changes not propagating or data structures winding up broken.
There are a number of thread-safe collections in java.util.collect.concurrent
that you might consider, otherwise you'll need to ensure you use synchronized
blocks or methods anywhere you're working with this list.
The most obvious problem that I found(and this might not be all) is that your array list is method specific. it is not static. Meaning that it can only be accessed by the method it originates in. the easiest fix for this is to add a static modifier to your array list when it is created and create it outside of the methods.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.