Android 同步 onSensorChanged?
Android synchronized onSensorChanged?
这是我的问题的后续:
我在思考应用程序的同步方法时遇到了一些困难
我正在轮询传感器并在传感器值发生变化时将其存储到数组中
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
方法既写入数组,又从数组读取写入数据库
我的问题是,onSensorChanged
方法应该同步吗?
最重要的是我没有漏掉任何数据。我需要每 10 毫秒存储一次当前传感器值 - none 可能会丢失。
所以据我了解,同步方法意味着 UI 线程将持有一个锁,并将传感器值写入数组。在此期间,由于锁定,执行程序线程无法从这些数组中读取。然后解除锁,然后执行线程加锁,读取数组,写入数据库,释放锁
我可能误解了这里同步方法的使用,特别是考虑到 onSensorChanged
是事件驱动的,我不确定它是如何发挥作用的
但似乎在这种情况下,我可能不会每 10 毫秒插入一次最新值。当 UI 线程建立锁时,执行线程无法将这些值写入数据库。到执行程序线程可以写入时,这些值现在已经有几毫秒了并且不准确
另一方面,同步意味着我不会遇到 UI 线程正在更改数组值,同时执行程序线程将一半更改的值插入数据库的情况
那么对于这种我需要每 10 毫秒插入最多 recent/accurate 传感器数据的情况,我应该使用同步方法吗?
您当前的代码不是线程安全的,因为 Runnable
使用与 UI 线程正在写入的数组相同的数组。调用 executor.execute(insertHandler);
后,无法保证 UI 线程不会获得另一个传感器事件并在 Runnable
将数组值写入数据库之前更改其中一个数组值。看来你明白这部分了。
要解决此问题,我根本不建议使用同步块,因为您似乎只想在 diffTime > POLL_FREQUENCY
时写出存储在数组中的任何值。 onSensorChanged(...)
方法本身只会在您代码中的 UI 线程上调用,因此您不必担心另一个线程在此方法中更改数组的值。
综上所述,您可以将数组的当前值存储在 Runnable
class 的新实例中。我知道在您之前的 post 中建议使用相同的实例,但这不会产生明显的差异。您甚至可以通过打开 Android Monitor 进行验证,并在您的应用程序运行时检查您的内存使用情况。通过存储当前值,现在在写出数据之前是否再次调用 onSensorChanged()
并不重要,因为您已经拥有所需数据的副本,该副本不会更改。
这是我在代码中的建议:
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);
这是我的问题的后续:
我在思考应用程序的同步方法时遇到了一些困难
我正在轮询传感器并在传感器值发生变化时将其存储到数组中
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
方法既写入数组,又从数组读取写入数据库
我的问题是,onSensorChanged
方法应该同步吗?
最重要的是我没有漏掉任何数据。我需要每 10 毫秒存储一次当前传感器值 - none 可能会丢失。
所以据我了解,同步方法意味着 UI 线程将持有一个锁,并将传感器值写入数组。在此期间,由于锁定,执行程序线程无法从这些数组中读取。然后解除锁,然后执行线程加锁,读取数组,写入数据库,释放锁
我可能误解了这里同步方法的使用,特别是考虑到 onSensorChanged
是事件驱动的,我不确定它是如何发挥作用的
但似乎在这种情况下,我可能不会每 10 毫秒插入一次最新值。当 UI 线程建立锁时,执行线程无法将这些值写入数据库。到执行程序线程可以写入时,这些值现在已经有几毫秒了并且不准确
另一方面,同步意味着我不会遇到 UI 线程正在更改数组值,同时执行程序线程将一半更改的值插入数据库的情况
那么对于这种我需要每 10 毫秒插入最多 recent/accurate 传感器数据的情况,我应该使用同步方法吗?
您当前的代码不是线程安全的,因为 Runnable
使用与 UI 线程正在写入的数组相同的数组。调用 executor.execute(insertHandler);
后,无法保证 UI 线程不会获得另一个传感器事件并在 Runnable
将数组值写入数据库之前更改其中一个数组值。看来你明白这部分了。
要解决此问题,我根本不建议使用同步块,因为您似乎只想在 diffTime > POLL_FREQUENCY
时写出存储在数组中的任何值。 onSensorChanged(...)
方法本身只会在您代码中的 UI 线程上调用,因此您不必担心另一个线程在此方法中更改数组的值。
综上所述,您可以将数组的当前值存储在 Runnable
class 的新实例中。我知道在您之前的 post 中建议使用相同的实例,但这不会产生明显的差异。您甚至可以通过打开 Android Monitor 进行验证,并在您的应用程序运行时检查您的内存使用情况。通过存储当前值,现在在写出数据之前是否再次调用 onSensorChanged()
并不重要,因为您已经拥有所需数据的副本,该副本不会更改。
这是我在代码中的建议:
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);