Android是否同步onSensorChanged? [英] Android synchronized onSensorChanged?

查看:145
本文介绍了Android是否同步onSensorChanged?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题的跟进内容: Android线程可运行性能

This is a followup to my question here: Android thread runnable performance

我在为我的应用同步方法时有些困难

I'm having some difficulty wrapping my head around synchronized methods for my app

我正在轮询传感器,并在传感器值发生变化时将其存储到数组中

I'm polling the sensors and storing the sensor values into arrays whenever they change

float[] accelerometerMatrix = new float[3];
float[] accelerometerWorldMatrix = new float[3];
float[] gyroscopeMatrix = new float[3];
float[] gravityMatrix = new float[3];
float[] magneticMatrix = new float[3];
float[] rotationMatrix = new float[9];

class InsertHandler implements Runnable {
        public void run() {
            //get values from arrays and insert into db
        }
    }

public void onSensorChanged(SensorEvent event) {
        sensor = event.sensor;

        int i = sensor.getType();
        if (i == MainActivity.TYPE_ACCELEROMETER) {
            accelerometerMatrix = event.values;
        } else if (i == MainActivity.TYPE_GYROSCOPE) {
            gyroscopeMatrix = event.values;
        } else if (i == MainActivity.TYPE_GRAVITY) {
            gravityMatrix = event.values;
        } else if (i == MainActivity.TYPE_MAGNETIC) {
            magneticMatrix = event.values;
        }

        long curTime = System.currentTimeMillis();
        long diffTime = (curTime - lastUpdate);

        // only allow one update every POLL_FREQUENCY.
        if(diffTime > POLL_FREQUENCY) {
            lastUpdate = curTime;

            //insert into database in background thread
            executor.execute(insertHandler);
        }
    }

每10毫秒,我的应用程序将(从数组中)获取当前传感器值,并使用单线程执行器将它们插入数据库中.因此,onSensorChanged方法既要写入数组,又要读取数组以写入数据库

Every 10ms, my app will take the current sensor values (from the arrays) and insert them into a database using a single thread executor. So the onSensorChanged method is both writing to the arrays, and reading from the arrays to write to database

我的问题是,onSensorChanged方法是否应该同步?

My question is, should the onSensorChanged method be synchronized?

最重要的是,我不会错过任何数据.每隔10毫秒,我需要存储一个传感器的当前值-不能错过任何一个.

The most important thing is that I don't miss any data. Every 10ms I need to store the current sensor values - none can be missed.

据我所知,同步方法意味着UI线程将持有一个锁,并将传感器值写入数组.在这段时间内,由于锁定,执行程序线程无法从这些数组中读取.然后解除锁定,然后执行程序线程锁定,从数组中读取并写入数据库,释放锁定

So to my understanding, a synchronized method means that the UI thread will hold a lock, and it will write the sensor values to the arrays. During this time, the executor thread cannot read from those arrays due to the lock. Then the lock is lifted and the executor thread then locks, reads from arrays, and write to database, releases lock

在这里我可能误解了同步方法的使用,尤其是考虑到onSensorChanged是事件驱动的,而且我不确定它如何发挥作用

I might be misunderstanding the use of synchronized methods here, especially given onSensorChanged is event driven and I'm not sure how that plays into it

但是似乎在这种情况下,我可能不会每10毫秒插入一次最新的值.当UI线程建立锁时,执行程序线程无法将这些值写入数据库.到执行程序线程可以写的时候,这些值现在已经过了几毫秒,而且不准确

But it seems that in a situation like this, I might not be inserting the most recent values every 10ms. When the UI thread establishes a lock, the executor thread can't write those values to the database. By the time the executor thread can write, the values would now be a few ms old and inaccurate

另一方面,同步将意味着我没有UI线程正在更改数组值的情况,而执行程序线程正在将一半更改的值插入数据库中

On the other hand, synchronization would mean that I dont have situations where the UI thread is changing the array values, while at the same time the executor thread is insert half changed values into the database

对于这种情况,我需要每10ms插入一次最新/准确的传感器数据,我应该使用同步方法吗?

So for this type of situation where I need to insert the most recent/accurate sensor data every 10ms, should I be using a synchronized method?

推荐答案

您当前的代码不是线程安全的,因为Runnable使用的是与UI线程相同的数组.一旦调用executor.execute(insertHandler);,就无法保证UI线程不会在Runnable将其写入数据库之前获取另一个传感器事件并更改数组值之一.看来您了解这部分.

Your current code is not thread safe as the Runnable is using the same arrays that the UI thread is writing to. Once you call executor.execute(insertHandler); there is no guarantee the UI thread won't get another sensor event and change one of the array values before the Runnable writes them to the database. It appears you understand this part.

要解决此问题,我完全不建议使用同步块,因为看来您只想写出diffTime > POLL_FREQUENCY时存储在数组中的所有值. onSensorChanged(...)方法本身只会在代码中的UI线程上调用,因此您不必担心在此方法中另一个线程会更改数组的值.

To fix this I would not recommend using a synchronized block at all as it seems you just want to write out whatever values are stored in the arrays when diffTime > POLL_FREQUENCY. The onSensorChanged(...) method itself will only ever be called on the UI thread in your code so you don't have to worry about another thread changing the value of the arrays while in this method.

所有这些,您可以做的是将数组的当前值存储在您的Runnable类的新实例中.我知道您以前的文章中建议使用相同的实例,但这不会产生明显的区别.您甚至可以通过打开Android Monitor进行验证,并在应用程序运行时检查内存使用情况.通过存储当前值,现在在写出数据之前是否再次调用onSensorChanged()都无关紧要,因为您已经拥有所需的数据副本,并且不会更改.

With all this said what you can do is store the current values of the arrays in a new instance of your Runnable class. I know it was suggested in your previous post to use the same instance but that will not make a noticeable difference. You can even verify by opening Android Monitor and check your memory usage as your application runs. By storing the current values it now won't matter if onSensorChanged() is called again before you write out the data because you already have a copy of the data you need that won't change.

这是我在代码中的建议:

Here is what I am suggesting in code:

class InsertHandler implements Runnable {
    final float[] accelerometerMatrix;
    final float[] accelerometerWorldMatrix;
    final float[] gyroscopeMatrix;
    final float[] gravityMatrix;
    final float[] magneticMatrix;
    final float[] rotationMatrix;

    public InsertHandler(float[] accelerometerMatrix, float[] accelerometerWorldMatrix,
            float[] gyroscopeMatrix, float[] gravityMatrix,
            float[] magneticMatrix, float[] rotationMatrix) {
        this.accelerometerMatrix = accelerometerMatrix;
        this.accelerometerWorldMatrix = accelerometerWorldMatrix;
        this.gyroscopeMatrix = gyroscopeMatrix;
        this.gravityMatrix = gravityMatrix;
        this.magneticMatrix = magneticMatrix;
        this.rotationMatrix = rotationMatrix;
    }

    public void run() {
        // use class field arrays values and insert into db
    }
}

然后将Runnable添加到executor时使用:

Runnable insertHandler = new InsertHandler(accelerometerMatrix, accelerometerWorldMatrix,
        gyroscopeMatrix, gravityMatrix, magneticMatrix, rotationMatrix);
executor.execute(insertHandler);

这篇关于Android是否同步onSensorChanged?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆