Java 多线程通信:原子变量如AtomicInteger的使用有多好?为什么没有原子浮动?
简介: 我想创建一个多线程的android应用程序。我的问题是线程之间的通信。我读了一些关于线程间通信的文章,遇到了类似于Looper/Handler设计的东西,它似乎非常复杂,还有原子变量,比如AtomicInteger。目前,我使用AtomicInteger作为通信工具,但由于我对Java不是很有经验,我不确定这在我的情况下是否不好/是否有更好的解决方案用于我的特定用途。当我注意到我实际上需要像AtomicFloat这样的东西时,我对我的方法有点怀疑,但它并不存在。我觉得我误用了这个概念。我还发现,你可以让自己成为一个原子浮点,但我只是不确定我是否走上了正确的道路,或者是否有更好的技术 问题: 使用原子变量并为我的特定目的(如下所述)同时实现AtomicFloat可以/好吗?还是有更好的方式处理通信? 迄今为止使用原子变量的应用程序的目的/架构: 我有4个线程,用于以下目的: 1.SensorThread:读取传感器数据并将最新值保存在原子变量中,如Java 多线程通信:原子变量如AtomicInteger的使用有多好?为什么没有原子浮动?,java,android,multithreading,Java,Android,Multithreading,简介: 我想创建一个多线程的android应用程序。我的问题是线程之间的通信。我读了一些关于线程间通信的文章,遇到了类似于Looper/Handler设计的东西,它似乎非常复杂,还有原子变量,比如AtomicInteger。目前,我使用AtomicInteger作为通信工具,但由于我对Java不是很有经验,我不确定这在我的情况下是否不好/是否有更好的解决方案用于我的特定用途。当我注意到我实际上需要像AtomicFloat这样的东西时,我对我的方法有点怀疑,但它并不存在。我觉得我误用了这个概念。我
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=++i如果i
是易失性int,而int j=i.incrementAndGet(),则code>不是原子的如果i
是AtomicInteger
,则code>是原子的。所以,除非你需要那种原子操作,你可以简单地使用一个易失性浮点。Volatile将保证在一个线程中所做的更改在另一个线程中可见。
public class SensorRead {
public java.util.Date dateTimeForSample;
public float value;
}