5

介绍:

我想创建一个多线程的 android 应用程序。我的问题是线程之间的通信。我阅读了有关线程之间的通信的文章,并且遇到了诸如 Looper/Handler 设计之类的东西,这似乎很复杂,还有诸如 AtomicInteger 之类的原子变量。目前,我使用 AtomicInteger 作为通信工具,但由于我在 Java 方面的经验不是很丰富,我不确定这对我的情况是否不利/是否有更好的解决方案来满足我的特定目的。当我注意到我实际上需要像 AtomicFloat 这样的东西时,我也对我的方法有点怀疑,但它并不存在。我觉得我错过了这个概念。我还发现你可以让自己成为 AtomicFloat,但我只是不确定我是否走在正确的道路上,或者是否有更好的技术。

问题: 为我的特定目的使用原子变量并实现 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

你基本上有一个读者作家的问题,有两个读者,(目前)只有一个作家。如果您只想在线程之间传递简单类型,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();
     }
}

这只会启用“仅一个编写器”或“多个读取器”方案来访问您的共享对象。

例如,这将使您能够使用如下所示的复杂类型:

public class SensorRead {

    public java.util.Date dateTimeForSample;

    public float value;

}

使用此数据类型时,您应该注意这两个字段是否已安全且原子地设置和修改。AtomicXXX 类型对象不再有用。

于 2012-09-25T11:38:29.577 回答
0

您必须首先问自己是否真的需要理论的功能AtomicFloat。与简单相比,您可以拥有的唯一好处volatile floatcompareAndSetandaddAndGet操作(因为我猜在浮点数的情况下递增和递减实际上没有意义)。

如果您真的需要这些,您可以通过研究以下代码来实现它们AtomicInteger

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

现在这里唯一的问题是compareAndSet使用浮点不存在的特定于平台的调用,因此您可能需要通过使用Float.floatToIntBits获取 int 的方法来模拟它,然后使用 CAS AtomicInteger,例如:

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 回答