5

Đây là một followup cho câu hỏi của tôi ở đây: Android thread runnable performanceAndroid được đồng bộ hóa trênSensorChanged?

Tôi đang gặp một số khó khăn quấn quanh đầu tôi phương pháp đồng bộ cho ứng dụng của tôi

Tôi bỏ phiếu các cảm biến và lưu trữ các giá trị cảm biến vào mảng bất cứ khi nào họ thay đổi

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); 
     } 
    } 

Mỗi 10ms, ứng dụng của tôi sẽ lấy giá trị cảm biến hiện tại (từ mảng) và chèn chúng vào cơ sở dữ liệu bằng trình xử lý chuỗi đơn. Vì vậy, phương pháp onSensorChanged là cả hai văn bản cho các mảng, và đọc từ các mảng để ghi vào cơ sở dữ liệu

Câu hỏi của tôi là, phương pháp onSensorChanged có được đồng bộ không?

Điều quan trọng nhất là tôi không bỏ lỡ bất kỳ dữ liệu nào. Mỗi 10ms tôi cần phải lưu trữ các giá trị cảm biến hiện tại - không ai có thể bỏ qua.

Vì vậy, với hiểu biết của tôi, một phương pháp đồng bộ có nghĩa là chuỗi giao diện người dùng sẽ giữ một khóa và nó sẽ ghi các giá trị cảm biến vào các mảng. Trong suốt thời gian này, chuỗi tác vụ không thể đọc từ các mảng đó do khóa. Sau đó, khóa được nâng lên và chuỗi lệnh thực thi sau đó khóa, đọc từ mảng và ghi vào cơ sở dữ liệu, phát hành khóa

Tôi có thể hiểu nhầm việc sử dụng các phương pháp đã đồng bộ ở đây, đặc biệt là onSensorChanged. làm thế nào mà chơi vào nó

Nhưng có vẻ như trong một tình huống như thế này, tôi có thể không chèn các giá trị gần đây nhất sau mỗi 10ms. Khi chuỗi giao diện người dùng thiết lập khóa, chuỗi trình thực thi không thể ghi các giá trị đó vào cơ sở dữ liệu. Vào thời điểm mà chuỗi thực thi có thể ghi, các giá trị giờ đây sẽ là một vài ms cũ và không chính xác

Mặt khác, đồng bộ hóa có nghĩa là tôi không có tình huống mà chuỗi giao diện người dùng thay đổi giá trị mảng. đồng thời, chuỗi tác nhân được chèn một nửa giá trị đã thay đổi vào cơ sở dữ liệu

Vì vậy, đối với loại tình huống này tôi cần chèn dữ liệu cảm biến gần đây nhất/chính xác 10ms một lần, tôi có nên sử dụng phương pháp đồng bộ không?

Trả lời

2

Mã hiện tại của bạn không phải là luồng an toàn vì Runnable đang sử dụng cùng một mảng mà chuỗi giao diện người dùng đang ghi. Khi bạn gọi executor.execute(insertHandler);, không đảm bảo rằng chuỗi giao diện người dùng sẽ không nhận được một sự kiện cảm biến khác và thay đổi một trong các giá trị mảng trước khi Runnable ghi chúng vào cơ sở dữ liệu. Có vẻ như bạn hiểu phần này.

Để khắc phục điều này, tôi sẽ không khuyên bạn nên sử dụng một khối đồng bộ ở tất cả vì có vẻ như bạn chỉ muốn viết ra bất kỳ giá trị nào được lưu trữ trong mảng khi diffTime > POLL_FREQUENCY. Chính phương thức onSensorChanged(...) sẽ chỉ được gọi trên chuỗi giao diện người dùng trong mã của bạn, do đó bạn không phải lo lắng về một luồng khác thay đổi giá trị của mảng trong khi ở phương thức này.

Với tất cả điều này, những gì bạn có thể làm là lưu trữ các giá trị hiện tại của các mảng trong một phiên bản mới của lớp Runnable của bạn. Tôi biết nó đã được đề xuất trong bài trước của bạn để sử dụng cùng một trường hợp nhưng điều đó sẽ không tạo ra sự khác biệt đáng chú ý. Bạn thậm chí có thể xác minh bằng cách mở Android Monitor và kiểm tra mức sử dụng bộ nhớ của bạn khi ứng dụng của bạn chạy.Bằng cách lưu trữ các giá trị hiện tại, bây giờ sẽ không thành vấn đề nếu onSensorChanged() được gọi lại trước khi bạn ghi dữ liệu vì bạn đã có một bản sao dữ liệu bạn cần sẽ không thay đổi.

Dưới đây là những gì tôi đang thấy trong mã:

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 
    } 
} 

Và sau đó khi bạn thêm Runnable đến executor sử dụng:

Runnable insertHandler = new InsertHandler(accelerometerMatrix, accelerometerWorldMatrix, 
     gyroscopeMatrix, gravityMatrix, magneticMatrix, rotationMatrix); 
executor.execute(insertHandler); 
Các vấn đề liên quan