我的应用程序正在运行Service
,它与多传感器腕带保持BLE连接。 Service
实现了腕带SDK的一些回调方法,这些方法每秒都会使用新数据调用几次。
我希望将来自不同传感器的这些数据放在相对于其时间戳的同一Observation
对象中。所有Observation
对象每隔60秒被推送到后端服务器,传感器数据被放在一起以减少发送这些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
方法的对象,用于将所有传感器数据放在同一秒内。
答案 0 :(得分:1)
如果我错了,请纠正我,但我没有理由浪费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值。
无论如何,这段代码应该让你知道如何避免阻塞线程并存储数据并发。
如果您对该代码有任何疑问,请告诉我。