I have an Android app that registers several Android sensors at approximately 100 Hz. Therefore, if I register 10 sensors, I write about 3,000 data per second to a file (each sensor usually has 3 entries). Now the problem is that I want to minimize the effect of this entry in the rest of the application. In particular, I don’t want logging to slow down the delivery of events ... I want to make sure that I receive events as soon as they happen, and not with a delay (I know there will always be some kind of delay because Android does not in real time and because of the "traction" nature of the Sensor event environment).
Next, I will describe my approach, which does not seem to work well. I would like suggestions for improvement.
My current procedure is ...
For each sensor, I create a separate stream with BlockingQueue of events for registration. Inside the stream, I have a while loop that gets pulled out of the queue and writes the file using a buffered writer. When the sensor manager delivers a new SensorEvent, the event is placed in the appropriate queue (thereby starting the IO file on another stream) so as not to delay the main stream to which SensorEvents are transmitted.
I want to receive events as soon as they appear, so it is important that I do not introduce any delays in the Sensor infrastructure. If, for example, I made an IO file directly in the onEvent callback, then I worry that events may begin to accumulate in the pipeline and that they will be outdated by the time they are finally delivered. The above approach mitigates these concerns.
But there is one more problem ...
, IO , . , (, 5 1 ). , IO , . :
-. , , , , . , IO, , , .
, . . , , , ... , . , , IO . ?
, , , - .
?
:
, . SensorEvent.
package io.pcess.utils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class NonblockingFileWriter {
private Thread thread = null;
private BufferedWriter writer = null;
private final Object writerLock = new Object();
private final BlockingQueue<String> data = new LinkedBlockingQueue<String>();
private volatile boolean running = false;
private class FileWritingRunnable implements Runnable {
@Override
public void run() {
try {
while (running) {
String string = data.take();
synchronized (writerLock) {
if (writer != null) {
writer.write(string);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close();
}
}
};
public NonblockingFileWriter(String filename) {
this(new File(filename));
}
public NonblockingFileWriter(File file) {
writer = createWriter(file);
if (writer != null) {
running = true;
}
thread = new Thread(new FileWritingRunnable());
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
public void append(String string) {
try {
data.put(string);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void close() {
running = false;
try {
synchronized (writerLock) {
if (writer != null) {
writer.close();
writer = null;
}
}
data.put("Exit");
} catch (Exception e) {
e.printStackTrace();
}
}
private BufferedWriter createWriter(File file) {
BufferedWriter writer = null;
if (!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return writer;
}
}
if (file.canWrite()) {
boolean append = true;
try {
synchronized (writerLock) {
writer = new BufferedWriter(new FileWriter(file, append));
}
} catch (IOException e) {
e.printStackTrace();
}
}
return writer;
}
}