首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android服务中传感器数据的数据并发

Android服务中传感器数据的数据并发
EN

Stack Overflow用户
提问于 2017-09-29 07:39:26
回答 1查看 89关注 0票数 1

我的应用程序正在运行一个Service,它包含一个到多传感器腕带的BLE连接。Service为腕带SDK实现了一些回调方法,这些方法每秒钟用新数据多次调用。

我想把这些数据,从不同的传感器,放在同一个Observation对象相对于它的时间戳。每60秒将所有Observation对象推送到后端服务器,将传感器数据放在一起,以减少发送这些Observation对象的开销。

下面的代码片段给出了我现在正在做的事情。我的问题是,while-loop in observationFetcher完全阻塞了应用程序。在不使用块while-loop的情况下,还有其他方法来同步这些传感器数据吗?

代码语言:javascript
复制
    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方法的对象,用于将所有传感器数据放在同一秒钟内。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-29 09:01:04

如果我错了,请纠正我,但我不认为有理由浪费CPU时间无限迭代。当然,我看不到整个代码,您的API可能不允许您做一些事情,但是我将以以下方式实现数据处理:

代码语言:javascript
复制
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值。

无论如何,这段代码应该让您知道如何避免阻塞线程并存储数据并发性。

如果你对密码有任何疑问,请告诉我。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46484053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档