Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多线程通信:原子变量如AtomicInteger的使用有多好?为什么没有原子浮动?_Java_Android_Multithreading - Fatal编程技术网

Java 多线程通信:原子变量如AtomicInteger的使用有多好?为什么没有原子浮动?

Java 多线程通信:原子变量如AtomicInteger的使用有多好?为什么没有原子浮动?,java,android,multithreading,Java,Android,Multithreading,简介: 我想创建一个多线程的android应用程序。我的问题是线程之间的通信。我读了一些关于线程间通信的文章,遇到了类似于Looper/Handler设计的东西,它似乎非常复杂,还有原子变量,比如AtomicInteger。目前,我使用AtomicInteger作为通信工具,但由于我对Java不是很有经验,我不确定这在我的情况下是否不好/是否有更好的解决方案用于我的特定用途。当我注意到我实际上需要像AtomicFloat这样的东西时,我对我的方法有点怀疑,但它并不存在。我觉得我误用了这个概念。我

简介:

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

问题: 使用原子变量并为我的特定目的(如下所述)同时实现AtomicFloat可以/好吗?还是有更好的方式处理通信?

迄今为止使用原子变量的应用程序的目的/架构:

我有4个线程,用于以下目的:

1.SensorThread:读取传感器数据并将最新值保存在原子变量中,如

AtomicFloat gyro_z,AtomicFloat gyro_y, ...
2.通信读取:与PC通信,解释来自套接字的命令,并根据原子整数设置应用程序的状态: 原子整数态

3.UIThread:显示来自的当前传感器值 原子浮球陀螺,原子浮球陀螺


4.ComputationThread:使用传感器值
AtomicFloat陀螺仪z、AtomicFloat陀螺仪y,…
和状态
AtomicInteger状态
通过USB执行计算和发送命令。

你必须首先问问自己是否真的需要理论
AtomicFloat
的功能。与简单的
volatile float
相比,惟一的好处是
compareAndSet
addAndGet
操作(因为我猜在float的情况下,增量和减量没有真正意义)

如果您确实需要这些,您可能可以通过研究原子整数的代码来实现它们,例如:

public final int addAndGet(int delta) {
    for (;;) { 
       int current = get();
       int next = current + delta;
       if (compareAndSet(current, next))
           return next;
    }
}
现在这里唯一的问题是
compareAndSet
使用浮点数不存在的特定于平台的调用,因此您可能需要使用
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;
    }
}

你基本上有一个读者-作者问题,两个读者(目前)只有一个作者。如果您只想在线程之间传递简单类型,那么AtomicInteger或类似实现的AtomicFloat就可以了

但是,一个更适合您使用更复杂数据类型的解决方案是ReadWriteLock,它可以保护您读取或写入对象数据的代码:

e、 g:

这将仅启用“仅一个写入程序”或“多个读取程序”方案来访问共享对象

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

public class SensorRead {

    public java.util.Date dateTimeForSample;

    public float value;

}

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

听起来你可以使用volatile float。请看这篇帖子:@Perroloco我读到了,但下面两个回复说其中一个使用了非常罕见的。在我看来,原子浮点数的存在似乎是非常合乎逻辑的。这就是为什么我质疑我使用them@assylias,如果一个线程正在读取变量,而另一个线程正在写入变量,那么volatile的使用不是会产生问题吗?volatile只需要始终接收变量的最新值,对吗?@DimitarM.H。是-基本上,AtomicInteger和volatile int之间的唯一区别是AtomicInteger提供了诸如incrementAndGet之类的原子操作。所以
intj=++ii
是易失性int,而
int j=i.incrementAndGet(),则code>不是原子的i
AtomicInteger
,则code>是原子的。所以,除非你需要那种原子操作,你可以简单地使用一个易失性浮点。Volatile将保证在一个线程中所做的更改在另一个线程中可见。
public class SensorRead {

    public java.util.Date dateTimeForSample;

    public float value;

}