我的应用程序正在运行一个Service,它包含一个到多传感器腕带的BLE连接。Service为腕带SDK实现了一些回调方法,这些方法每秒钟用新数据多次调用。
我想把这些数据,从不同的传感器,放在同一个Observation对象相对于它的时间戳。每60秒将所有Observation对象推送到后端服务器,将传感器数据放在一起,以减少发送这些Observation对象的开销。
下面的代码片段给出了我现在正在做的事情。我的问题是,while-loop in observationFetcher完全阻塞了应用程序。在不使用块while-loop的情况下,还有其他方法来同步这些传感器数据吗?
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方法的对象,用于将所有传感器数据放在同一秒钟内。
发布于 2017-09-29 09:01:04
如果我错了,请纠正我,但我不认为有理由浪费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秒将其发送到某个地方。由于并发性存在问题,此代码仍然不完美。例如,如果两个gsr值首先出现,然后是一个ibi值,那么我们将丢失第一个gsr值。
无论如何,这段代码应该让您知道如何避免阻塞线程并存储数据并发性。
如果你对密码有任何疑问,请告诉我。
https://stackoverflow.com/questions/46484053
复制相似问题