I'm writing a simple app that constantly reads some data from serial port over bluetooth and then draws that data on 2 charts. I came up with an idea of buffering that data to byte buffer and then reading it from some other part of the code. The problem is that I have to read that data quite frequently (reading only 5 bytes at once) and I have some issues with synchronization of the threads. The serial port reading part is not allowing the printing thread to read anything most of the time. Sometimes it gets through and prints some data. These 2 are the only threads that use buffer
as the locking object.
I think I might've missunderstood some basic synchronization principles, but I'm starting to run out of ideas how can I solve this issue.
Reading from serial port part:
public void startReading() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
resetBuffer();
read = true;
try {
serialPort.purgePort(SerialPort.PURGE_RXCLEAR);
byte[] buf = new byte[5];
int bytes;
while (read) {
synchronized (buffer) {
try {
bytes = inputStream.blockingRead(buf);
System.out.println(buf);
System.arraycopy(buf, 0, buffer, bufferPos, bytes);
bufferPos += buf.length;
buffer.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (SerialPortException e) {
e.printStackTrace();
}
}
});
thread.start();
}
Printing data part (in loop):
synchronized (buffer) {
while (serialPortConnection.getBufferLength() < 5) {
try {
buffer.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
readBytesToStringBuffer();
printLineIfAvailable();
while (read) {
synchronized (buffer) {
try {
bytes = inputStream.blockingRead(buf);
Your problem is not in reading often; it is in blocking. You acquire the monitor on buffer
and then enter a blocking I/O call. You spend precious little time outside of that call, thus outside of the synchronized
block.
First read from port outside of synchronized
, then acquire the monitor to transfer the data to a shared structure.