У меня есть несколько потоков (runnables) в моей программе. По теме обращается сообщение RS232. Моя проблема заключается в том, что код внутри цикла не выполняется в том порядке, что написано:Как завершить цикл до завершения метода?
while(!serialData.dataToSend.isEmpty())
{
try {
SerialMsgToSend msgObject = serialData.dataToSend.remove();
if(msgObject.type == msgObject.HOLDING_REGISTER)
{
Thread.sleep(COMMAND_WAIT_TIME);
Toolkit.getDefaultToolkit().beep();
modBusManager.singleRegisterWriteToMultipleRegisters(msgObject.unit, msgObject.startRegisterAdress, msgObject.data);
}
else if(msgObject.type == msgObject.COIL)
{
Thread.sleep(COMMAND_WAIT_TIME);
Toolkit.getDefaultToolkit().beep();
modBusManager.writeToCoil(msgObject.unit, msgObject.startRegisterAdress, msgObject.data[0] == 1);
}
Thread.sleep(5000);
readUnitsData(msgObject.unit);
Thread.sleep(5000);
if(msgObject.RESPONSE > 0)
{
serialData.listeners[msgObject.unit - 1].sendResponseToServer(msgObject.RESPONSE);
}
} catch (Exception ex) {
log.error("Exception on sending data: " + ex.toString());
}
}
Сначала я пишу в ModBus регистре с вызовом:
modBusManager.singleRegisterWriteToMultipleRegisters(msgObject.unit, msgObject.startRegisterAdress, msgObject.data);
После того, что я хочу подождать 5 секунд эти регистры обновляются, затем читают их и отправляют информацию на сервер.
Я прочитал данные с вызова метода:
readUnitsData(msgObject.unit);
И тогда я использую слушателя сказать другой поток для передачи данных на сервер:
serialData.listeners[msgObject.unit - 1].sendResponseToServer(msgObject.RESPONSE);
Моя проблема заключается в том, что данные передаются в сервер, прежде чем он будет прочитан/обновлен, поэтому отправлю старые данные. Я использую этот код в том порядке, в котором он написан. Я использую потоки неправильно или что может быть проблемой?
Вот метод, который я называю читать данные:
private void readUnitsData(int unitID)
{
if(mtxData.climatList[unitID] != null)
{
try
{
log.info("Serial reading data for: " + unitID);
int[] coils = modBusManager.readCoils(unitID + 1,0,87);
String[] holding = modBusManager.readHoldingRegisters(unitID + 1,0,64); //(int slaveAdress, int registerAdress, int registerQuntaity)
if(coils != null && holding != null)
{
System.out.println("send to listner: " + unitID);
serialData.listeners[unitID].newHoldingAndCoilData(holding, coils);
}
} catch (Exception ex)
{
log.error("Exception on run: " + ex.toString());
}
}
}
И метод внутри другого работоспособной, который подключен к слушателю:
@Override
public void sendResponseToServer(int responseType)
{
try
{
log.info("listener for sendStatusToServer called: " + responseType);
Thread.sleep(15000);
switch(responseType)
{
case 1:
communicationManager.sendStatus();
break;
case 2:
communicationManager.sendSettings();
break;
}
}catch(Exception ex)
{
log.error("Exception on sendResponseToServer: " + ex);
}
}
От отправленного кода я не вижу причин, почему это не должно выполняться в письменном порядке. За исключением появления «Исключения». Вы уверены, что ни один из ваших других потоков не закаляет ваши объекты коммуникации? –
@MarkusMitterauer У меня есть только один поток, который начинает писать/читать сообщения в ModBus. Для меня это похоже на тот поток, который обрабатывает RS232, всегда ждет, когда слушатель завершит работу до вызова readUnitsData(). Поскольку я добавил увеличенный Thread.sleep (15000) к большему числу, и с этим увеличилось время readUnitsData(). Можно ли использовать runnables и прослушиватели так, как я их использую, или что может быть проблемой? – Jure
Ну, боюсь, я не знаю другого совета, кроме как попробовать [отладить] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) вашу программу и посмотреть, что на самом деле происходит. - Как я уже сказал, я не вижу проблем в коде, который вы предоставили, но многопоточность является сложной темой, и в коде, который вы запускаете в других потоках, могут быть еще ловушки. Возьмите это приложение. Выполните только один поток. (удаленный) отладить его и/или добавить больше логических операторов. Поймите, что происходит. –