简体   繁体   中英

Java - Can't access arraylist in another class

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:

在此处输入图片说明 TemperatureSensor :

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM