У меня какое-то странное поведение при использовании ArrayBlockingQueue, которое я использую для связи между определенными шагами в приложении Java.
Я использую 1 статическую очередь ArrayBlockingQueue, инициализированную следующим образом:
protected static BlockingQueue<long[]> commandQueue;
За ним следует конструктор, в одной из строк которого есть this:
commandQueue = new ArrayBlockingQueue<long[]>(amountOfThreads*4);
Где amountOfThreads
задается как аргумент конструктора.
Затем у меня есть производитель, который создает массив long[2]
, дает ему некоторые значения, а затем предлагает его в очередь, затем я изменяю одно из значений массива сразу после него и еще раз предлагаю его в очередь:
long[] temp = new long[2];
temp[0] = currentThread().getId();
temp[1] = gyrAddress;//Address of an i2c sensor
CommunicationThread.commandQueue.offer(temp);//CommunicationThread is where the commandqueue is located
temp[1] = axlAddress;//Change the address to a different sensor
CommunicationThread.commandQueue.offer(temp);
Затем потребитель возьмет эти данные и откроет соединение i2c с определенным датчиком, получит некоторые данные от указанного датчика и передаст данные обратно, используя другую очередь. На данный момент, однако, я установил, что потребитель просто потребляет голову и печатает данные.
long[] command = commandQueue.take();//This will hold the program until there is at least 1 command in the queue
if (command.length!=2){
throw new ArrayIndexOutOfBoundsException("The command given is of incorrect format");
}else{
System.out.println("The thread with thread id " + command[0] + " has given the command to get data from address " +Long.toHexString(command[1]));
}
Теперь для тестирования у меня есть поток производителя с этими адресами (byte) 0x34, (byte)0x44
Если все идет правильно, мой вывод должен быть:
The thread with thread id 14 has given the command to get data from address 44
The thread with thread id 14 has given the command to get data from address 34
Однако я получаю:
The thread with thread id 14 has given the command to get data from address 34
The thread with thread id 14 has given the command to get data from address 34
Это означало бы, что он отправляет временный массив после его изменения.
Что я сделал, чтобы попытаться это исправить: я попробовал сон, если я добавил сон на 150 мс, тогда ответ правильный. Однако этот метод совершенно очевидно повлияет на производительность... Поскольку метод предложения возвращает истину, я попробовал следующий фрагмент кода.
boolean tempBool = false;
while(!tempBool){
tempBool = CommunicationThread.commandQueue.offer(temp);
System.out.println(tempBool);
}
Который выводит истину. Это не повлияло.
Я попытался напечатать temp[1]
после этого цикла while, и в этот момент это правильное значение. (Он печатает 44
, однако потребитель получает 34
)
Скорее всего, это проблема синхронизации, однако я думал, что цель объекта на основе BlockingQueue состоит в том, чтобы решить эту проблему.
Мы будем очень признательны за любую помощь или предложение по работе этой BlockingQueue. Позвольте мне закончить на заметке, что я впервые работаю с очередями между потоками в java и что окончательная программа будет работать на raspberry pi с использованием библиотеки pi4j для связи с датчиками.