我的应用程序正在运行一个Service
,该cc与多传感器腕带保持BLE连接。 Service
为腕带SDK实现一些回调方法,这些方法每秒钟都会被新数据调用几次。
我想将来自不同传感器的这些数据放入相对于其时间戳的同一Observation
对象中。每隔60秒将所有Observation
对象推送到后端服务器,将传感器数据放在一起以减少发送这些Observation
对象的开销。
我现在正在做的事情显示在下面的代码片段中。我的问题是while
中的observationFetcher
循环完全阻塞了应用程序。是否有其他方法可以在不使用块while
循环的情况下同步这些传感器数据?
observationFetcher = new Runnable() {
@Override
public void run() {
while (isRecording) {
if (lastMillis != currentMillis) {
Observation obs = sm.getValues();
obs.setPropertyAsString("gateway.id", UUID);
observations.add(obs);
lastMillis = currentMillis;
}
}
}
};
public void didReceiveGSR(float gsr, double timestamp) {
long t = System.currentTimeMillis() / 1000;
sm.setGsrValue(t, gsr);
currentMillis = t;
}
public void didReceiveIBI(float ibi, double timestamp) {
sm.setIbiValue(ibi);
}
sm
是具有synchronized
方法的对象,用于将同一秒内的所有传感器数据放在一起。 最佳答案
如果我错了,请纠正我,但是我看不出浪费CPU时间无限迭代的原因。当然,我看不到完整的代码,并且您的API可能不允许您执行某些操作,但是我将通过以下方式实现数据处理:
final class Observation {
private float gsr;
private float ibi;
public Observation(float gsr, float ibi) {
this.gsr = gsr;
this.ibi = ibi;
}
// getters & setters
}
public final class Observations {
private final ConcurrentHashMap<Long, Observation> observations = new ConcurrentHashMap<>();
public void insertGsrValue(long timestamp, float gsr) {
for (;;) {
Observation observation = observations.get(timestamp);
if (observation == null) {
observation = observations.putIfAbsent(timestamp, new Observation(gsr, 0.0f));
if (observation == null) {
return;
}
}
if (observations.replace(timestamp, observation, new Observation(gsr, observation.getIbi()))) {
return;
}
}
}
public void insertIbiValue(long timestamp, float ibi) {
for (;;) {
Observation observation = observations.get(timestamp);
if (observation == null) {
observation = observations.putIfAbsent(timestamp, new Observation(0.0f, ibi));
if (observation == null) {
return;
}
}
if (observations.replace(timestamp, observation, new Observation(observation.getGsr(), ibi))) {
return;
}
}
}
public List<Observation> getObservations() {
return new ArrayList<>(observations.values());
}
public void clear() {
observations.clear();
}
}
public final class ObservationService extends Service {
private final Observations observations = new Observations();
private volatile long currentMillis;
private HandlerThread handlerThread;
private Handler handler;
@Override
public void onCreate() {
super.onCreate();
handlerThread = new HandlerThread("observations_sender_thread");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
sendData();
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(60));
}
}, TimeUnit.SECONDS.toMillis(60));
}
@Override
public void onDestroy() {
handlerThread.quit();
}
private void sendData() {
List<Observation> observationList = observations.getObservations();
observations.clear();
// send observation list somehow
}
public void didReceiveGSR(float gsr, double timestamp) {
// assuming this is called on a worker thread
long t = System.currentTimeMillis() / 1000;
observations.insertGsrValue(t, gsr);
currentMillis = t;
}
public void didReceiveIBI(float ibi, double timestamp) {
// assuming this is called on a worker thread
observations.insertIbiValue(currentMillis, ibi);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
因此,此代码的作用是将传感器中的新值插入到哈希图中,然后每60秒将其发送到某个地方。由于并发性问题,此代码仍不完美。例如,如果首先出现2个gsr值,然后是一个ibi值,那么我们将丢失第一个gsr值。
无论如何,这段代码应该给您一个思路,如何避免阻塞线程并存储数据并发。
如果您对代码有任何疑问,请告诉我。