2012-09-25 13 views
5

Giới thiệu:Giao tiếp đa luồng: mức độ sử dụng các Biến Nguyên tử như AtomicInteger tốt như thế nào? tại sao không có AtomicFloat?

Tôi muốn tạo ứng dụng Android đa luồng. Vấn đề của tôi là giao tiếp giữa các chủ đề. Tôi đọc về giao tiếp giữa các chủ đề và tôi bắt gặp các công cụ như thiết kế Looper/Handler, có vẻ khá liên quan và các Biến Nguyên tử như AtomicInteger. Hiện tại, tôi đã sử dụng AtomicInteger làm giao tiếp nhưng vì tôi không có nhiều kinh nghiệm về Java, tôi không chắc liệu đó có phải là điều xấu trong trường hợp của tôi không/nếu có giải pháp tốt hơn cho mục đích cụ thể của tôi. Ngoài ra tôi có một chút nghi ngờ về phương pháp của mình, khi tôi nhận thấy tôi cần một cái gì đó giống như AtomicFloat, nhưng nó không tồn tại. Tôi cảm thấy như tôi đang bỏ lỡ khái niệm này. Tôi cũng thấy rằng bạn có thể làm cho mình một AtomicFloat, nhưng tôi chỉ không chắc chắn nếu tôi đang đi đúng hướng hoặc nếu có một kỹ thuật tốt hơn.

Câu hỏi: Sử dụng AtomicFloat cho mục đích cụ thể của tôi cũng tốt hay không (được mô tả bên dưới) hoặc có cách xử lý giao tiếp tốt hơn không?

Mục đích/Kiến trúc của App sử dụng AtomicVariables cho đến nay:

Tôi có 4 chủ đề với mục đích sau:

1.SensorThread: Đọc dữ liệu cảm biến và lưu giá trị mới nhất trong AtomicVariables như

AtomicFloat gyro_z,AtomicFloat gyro_y, ... 

2.Thông báoThay đổi: Tạo thành ổ cắm và đặt trạng thái của ứng dụng theo thuật ngữ của một AtomicInteger: Trạng thái AtomicInteger;

3.UIThread: Hiển thị các giá trị cảm biến hiện tại từ AtomicFloat gyro_z, AtomicFloat gyro_y,

4.ComputationThread: sử dụng cảm biến giá trị AtomicFloat gyro_z,AtomicFloat gyro_y, ... và tiểu bang AtomicInteger state để thực hiện tính toán và gửi lệnh qua USB.

+0

Có vẻ như bạn có thể làm gì với phao dễ bay hơi. – assylias

+0

Xin hãy nhìn vào bài đăng này: http://stackoverflow.com/questions/5505460/java-is-there-no-atomicfloat-or-atomicdouble –

+0

@Perroloco Tôi đọc mà, nhưng thấp hơn hai trả lời đã nói rằng người ta sử dụng nó rất hiếm. Đối với tôi nó có vẻ rất hợp lý mà AtomicFloat nên tồn tại. rằng tại sao tôi đặt câu hỏi về việc sử dụng chúng –

Trả lời

1

bạn về cơ bản có một độc giả nhà văn prob lem, với hai độc giả và (cho thời điểm này) chỉ có một nhà văn. Nếu bạn chỉ muốn truyền các kiểu đơn giản giữa các luồng, một AtomicInteger hoặc một AtomicFloat được triển khai tương tự sẽ chỉ là tốt.

Tuy nhiên, một giải pháp có sức chứa hơn, mà sẽ cho phép bạn làm việc với các kiểu dữ liệu phức tạp hơn sẽ là một ReadWriteLock bảo vệ mã nơi bạn đọc hoặc ghi dữ liệu đối tượng của bạn:

ví dụ:

private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //the reentrant impl 

.... 

public void readMethod() { 

    readWriteLock.readLock().lock(); 

    try { 
     //code that simply _reads_ your object 
    } finally { 
     readWriteLock.readLock().unlock(); 
    } 

} 

public void writeMethod() { 

    readWriteLock.writeLock().lock(); 

    try { 
     //... code that modifies your shared object/objects 
    } finally { 
     readWriteLock.writeLock().unlock(); 
    } 
} 

Điều này sẽ chỉ bật các kịch bản "một người viết" hoặc "nhiều người đọc" để truy cập vào các đối tượng được chia sẻ của bạn.

Điều này sẽ cho phép bạn ví dụ để làm việc với một kiểu phức trông như thế này:

public class SensorRead { 

    public java.util.Date dateTimeForSample; 

    public float value; 

} 

Trong khi sử dụng kiểu dữ liệu này, bạn nên quan tâm nếu hai lĩnh vực được thiết lập và sửa đổi một cách an toàn và nguyên tử. Các đối tượng kiểu AtomicXXX không còn hữu dụng nữa.

+0

cảm ơn bạn, tôi đoán tôi có thể dính vào kế hoạch biến nguyên tử của tôi. –

0

Trước tiên bạn phải tự hỏi mình có thực sự cần chức năng của lý thuyết AtomicFloat hay không. Lợi ích duy nhất bạn có thể có trên một đơn giản volatile float là các hoạt động compareAndSet và các hoạt động addAndGet (vì tôi đoán tăng và giảm không thực sự có ý nghĩa trong trường hợp nổi).

Nếu bạn thực sự cần những người, bạn có thể có thể thực hiện chúng bằng cách nghiên cứu các quy tắc ứng AtomicInteger ví dụ:

public final int addAndGet(int delta) { 
    for (;;) { 
     int current = get(); 
     int next = current + delta; 
     if (compareAndSet(current, next)) 
      return next; 
    } 
} 

Bây giờ vấn đề duy nhất ở đây là compareAndSet sử dụng cuộc gọi nền tảng cụ thể không tồn tại cho nổi , vì vậy có thể bạn sẽ cần phải bắt chước nó bằng cách sử dụng phương pháp Float.floatToIntBits để có được một int, sau đó sử dụng CAS của AtomicInteger, một cái gì đó như:

private volatile float value; 

public final boolean compareAndSet(float expect, float next) { 
    AtomicInteger local = new AtomicInteger(); 
    for(;;) { 
     local.set(Float.floatToIntBits(value)); 
     if(local.compareAndSet(Float.floatToIntBits(expect), 
           Float.floatToIntBits(next)) { 
      set(Float.intBitsToFloat(local.get())); 
      return true; 
     } 
    } 
} 

public final float addAndGet(float delta) { 
    for (;;) { 
     float current = get(); 
     float next = current + delta; 
     if (compareAndSet(current, next)) 
      return next; 
    } 
} 
Các vấn đề liên quan