5

はじめに:

マルチスレッドの Android アプリを作成したいと考えています。私の問題は、スレッド間の通信です。スレッド間の通信について読んだところ、非常に複雑な Looper/Handler 設計や、AtomicInteger のような Atomic Variables などに出くわしました。今のところ、コミュニケーションとして AtomicInteger を使用しましたが、Java の経験があまりないので、それが私の場合に悪いのかどうか、または特定の目的のためのより良い解決策があるかどうかはわかりません。また、実際に AtomicFloat のようなものが必要であることに気付いたとき、私は自分の方法に少し疑いを持っていましたが、それは存在しませんでした。概念を誤用しているように感じました。また、自分で AtomicFloat を作成できることもわかりましたが、これが正しい方法なのか、それともより良い手法があるのか​​はわかりません。

質問: Atomic Variables を使用して、特定の目的 (以下で説明) のために AtomicFloat も実装することは問題ありませんか?それとも、通信を処理するためのより良い方法はありますか?

これまでの AtomicVariables を使用したアプリの目的/アーキテクチャ:

次の目的で4つのスレッドがあります。

1.SensorThread: センサー データを読み取り、最新の値を AtomicVariables のように保存します。

AtomicFloat gyro_z,AtomicFloat gyro_y, ...

2.CommunicationThread: PC との通信は、ソケットから来るコマンドを解釈し、AtomicInteger: AtomicInteger 状態に関してアプリの状態を設定します。

3.UIThread: AtomicFloat gyro_z、AtomicFloat gyro_y、

4.ComputationThread: センサーの値AtomicFloat gyro_z,AtomicFloat gyro_y, ...と状態AtomicInteger stateを使用して計算を実行し、USB 経由でコマンドを送信します。

4

2 に答える 2

1

基本的に、リーダーとライターの問題があり、リーダーが 2 人と (今のところ) ライターが 1 つしかありません。単純な型をスレッド間で渡したいだけなら、AtomicInteger または同様に実装された AtomicFloat で十分です。

ただし、より複雑なデータ型を操作できるようにする、より柔軟なソリューションは、オブジェクト データを読み書きするコードを保護する ReadWriteLock です。

例えば:

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

これにより、共有オブジェクトにアクセスするための「1 つのライターのみ」または「複数のリーダー」シナリオのみが有効になります。

これにより、たとえば、次のような複合型を操作できます。

public class SensorRead {

    public java.util.Date dateTimeForSample;

    public float value;

}

このデータ型を使用している間は、2 つのフィールドが安全かつアトミックに設定および変更されているかどうかに注意する必要があります。AtomicXXX タイプのオブジェクトはもはや役に立ちません。

于 2012-09-25T11:38:29.577 に答える
0

まず、理論上の機能が本当に必要かどうかを自問する必要がありますAtomicFloat。単純なものに比べて得られる唯一の利点volatile floatは、compareAndSetaddAndGet操作です(フロートの場合、インクリメントとデクリメントは実際には意味がないと思うので)。

それらが本当に必要な場合は、AtomicIntegerたとえば次のコードを調べることで実装できます。

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

ここでの唯一の問題はcompareAndSet、floatには存在しないプラットフォーム固有の呼び出しを使用することです。したがってFloat.floatToIntBits、intを取得するメソッドを使用してエミュレートし、次のAtomicIntegerようなCASを使用する必要があります。

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;
    }
}
于 2012-09-25T11:20:57.023 に答える