我有一个可运行的类“TemperatureSensor”,它定期将新的随机浮点值添加到数组列表TemperatureList作为对象温度。然后,数组中最后添加的对象(索引0)从RMI客户端发送到RMI服务器 - 这没有问题。
然而,当我单击GUI上的一个按钮来显示此对象数组的大小时,我总是得到0.如果我从RMI客户端类打印出数组的大小,它会显示正确的大小。
我的问题是,如何正确地从多个类访问相同的数组?
以下是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();
}
}
}
型号:
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();
}
}
以下是我启动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();
}
}
答案 0 :(得分:1)
您的问题与课程无关。
您运行两个单独的应用程序。一个运行RMIsensorClient
,一个运行GUI
。他们对彼此一无所知,您的RMIsensorClient
和Controller
拥有自己独立的ModelManager
个实例,并且您无法在任何地方共享任何数据。
您需要以某种方式使您想要在GUI中显示的数据可用。
一种解决方案可能是使用网络接口。创建两个不同的ModelManager
,一个打开并收听ServerSocket,另一个使用getLatestTemperatureData()
中的Socket连接到另一个。{/ p>
在您的RMIsensorClient
中使用前者,在GUI
Controller
中使用后者。
用Java研究网络。
这是一个非常粗略的解决方案,但是有很多很棒的教程可以在多个Java应用程序之间进行网络连接和共享数据。
答案 1 :(得分:0)
您尚未加入TemperatureList
实施,但如果您说它是ArrayList
,那么您可能不是properly synchronizing access across threads。您必须正确地同步跨线程工作,否则您将遇到某种未定义的行为,例如更改未传播或数据结构崩溃。
您可能会考虑java.util.collect.concurrent
中有许多线程安全的集合,否则您需要确保在使用此列表的任何位置使用synchronized
块或方法。< / p>
答案 2 :(得分:-1)
我发现的最明显的问题(可能不是全部)是您的数组列表是特定于方法的。它不是静止的。这意味着它只能通过它所源自的方法来访问。最简单的解决方法是在创建数组列表时为其添加静态修饰符,并在方法之外创建它。