我正在为学校做一个项目。我们正在建造一个可以装卸船只的港口。控件部分在Netbeans
中进行,模拟在JME
中。
我们通过套接字将数据从Netbeans发送到JME
。 JME正在运行一个来自Netbeans
的输入的服务器插件。
例如Netbeans
发送一个容器的ID,JME
中的起重机获取该容器并将其放在岸上,以便车辆可以将其取出。
我们更改主(Main.count = 2
)中的计数,以便SimpleUpdate
可以调用方法。问题是有时候东西会被跳过。此外,我认为当我们发送更多信息时,例如正在装载集装箱的车辆,情况会变得更糟。我怎样才能解决这个问题?还有其他方法可以建立良好的联系吗?
代码:
Netbeans的
发送客户
public static void run() throws Exception
{
Socket socket = new Socket("Localhost", 4321);
out = new ObjectOutputStream(socket.getOutputStream());
}
//Sent arraystring to Simulation
public void sent(String sentString){
try {
out.writeObject(sentString);
} catch (IOException ex) {
Logger.getLogger(CommunicationWithSimulatoin.class.getName()).log(Level.SEVERE, null, ex);
}
}
主要发送一些例子
for(int i = Calculator.getContainersFromMaritime(); i > 1; i--)
{
Thread.sleep(50);
sim.sent("craneCon;" + i + ";");
System.out.println(i);
}
JME
监听
public static void Listener() throws Exception {
boolean isRunning = true;
//Creates the server socket
ServerSocket sSocket = new ServerSocket(4321);
//Acception a connection from the client
Socket socket = sSocket.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
//Get the input from the client
while (isRunning) {
//Reads and prints the input
test = (String) in.readObject();
System.out.println(test);
String[] parts = receivedString.split(";");
if(parts[0].equals("ContainerPositionsMaritime"))
{
Maritime.ContainersOnBoard = receivedString.split(";");
Main.count = 0;
}
if(parts[0].equals("craneCon"))
{
int containerId = Integer.parseInt(parts[1]);
SeagoingCranes.idContainer = containerId;
Main.count = 2;
}
}
}
Main simpleupdate
public void simpleUpdate(float tpf) {
if(count == 0)
{
InitContainers();
//martime.setLocalTranslation(0, 500.0f, 0);
count = 999;
}
if(count == 2)
{
InitCrane(SeagoingCranes.idContainer);
count = 999;
}
if(martime != null)
{
martime.move(0,0,0.25f*tpf);
}
}
答案 0 :(得分:0)
您的计划存在许多问题。
首先 - 你有潜在的竞争和线程争用问题,因为你有“计数”,我假设SimpleApplication
内的整数值正在从一个线程修改并从另一个线程读取。除非将值声明为volatile,否则可能会导致各种意外问题和奇怪的行为,甚至不建议将其声明为volatile。
你的主要问题(即使不考虑微妙的问题)是由于simpleUpdate()
你在扫描计数然后根据计数采取行动这一事实。当你的jME3应用程序正在运行时,每个帧都会调用simpleUpdate()
一次。
如果您在一个框架中收到多条消息,则只有最后一条消息会被执行,因为在下一次simpleUpdate()
运行之前,计数将再次被修改。
执行此操作的最佳方法是使用app.enqueue()
。
if(parts[0].equals("ContainerPositionsMaritime"))
{
final ContainersOnBoard containers = receivedString.split(";");
mainApp.enqueue(new Callable<Spatial>() {
public Spatial call() throws Exception {
mainApp.InitContainers(containers);
return null;
}
});
}
}
您可以从simpleUpdate()
删除所有现有代码。
Callable
您enqueue
将在下次更新时从JME3线程回调,并处理容器的添加。通过为每个不同的命令执行类似的操作,它将enqueue
并随着时间的推移处理所有命令。您可以enqueue
任意多个命令,它们都将被处理。
一般来说,您应该阅读AppStates,Controls和线程模型,因为它们可以让您的代码更加结构化和有条理。
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:application_states
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_controls
P.S。您应该尝试遵循Java样式/编码约定 - 例如,方法应该以小写开头。 initContainers不是InitContainers。