我找到了AtomicInteger
,AtomicLong
,但是其中是AtomicFloat
(或AtomicDouble
)?也許有一些竅門?Java:有沒有AtomicFloat或AtomicDouble?
回答
爲java.util.concurrent
package狀態下面的API文檔:
[...]另外,僅針對那些在預定的應用中很常用的類型提供的類。例如,沒有用於表示字節的原子類。在那些您不希望這樣做的罕見情況下,您可以使用
AtomicInteger
來保存字節值,並進行適當的轉換。 您也可以使用Float.floatToIntBits
和Float.intBitstoFloat
轉換來保存花車,並使用Double.doubleToLongBits
和Double.longBitsToDouble
轉換進行雙擊。
我不是說這是一個方便的解決方案,但是這似乎是解釋。我想你可能會想換一個AtomicInteger
,並提供訪問方法getFloat
/setFloat
等
事實上,我身邊一個寫。在這裏你去:
import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.Float.*;
class AtomicFloat extends Number {
private AtomicInteger bits;
public AtomicFloat() {
this(0f);
}
public AtomicFloat(float initialValue) {
bits = new AtomicInteger(floatToIntBits(initialValue));
}
public final boolean compareAndSet(float expect, float update) {
return bits.compareAndSet(floatToIntBits(expect),
floatToIntBits(update));
}
public final void set(float newValue) {
bits.set(floatToIntBits(newValue));
}
public final float get() {
return intBitsToFloat(bits.get());
}
public float floatValue() {
return get();
}
public final float getAndSet(float newValue) {
return intBitsToFloat(bits.getAndSet(floatToIntBits(newValue)));
}
public final boolean weakCompareAndSet(float expect, float update) {
return bits.weakCompareAndSet(floatToIntBits(expect),
floatToIntBits(update));
}
public double doubleValue() { return (double) floatValue(); }
public int intValue() { return (int) get(); }
public long longValue() { return (long) get(); }
}
也可以在Guava中使用AtomicDouble http://docs.guava-libraries.googlecode.com/git-history/v11.0.2/javadoc/com/google/common/util/concurrent/AtomicDouble.html – codeplay 2013-10-31 09:41:33
這是缺少一個這個功能很有用:'addAndGet'(或者'getAndAdd';並不重要)。 Guava'AtomicDouble'和Java 8'DoubleAdder'都有。所有這些關於用例的問題:自然地累積來自不同線程的殘差總和! – 2016-01-14 17:11:20
@JimPivarski,'addAndGet'可以以'getAndSet'實現的相同方式實現。只需通過支持AtomicInteger的位。 – aioobe 2016-01-15 11:55:25
你也許可以使用AtomicReference<Float>
來代替。我認爲AtomicInteger
和AtomicLong
可以獲得特殊的課程,因爲它們對計算很有用。
'AtomicReference.compareAndSet'通過身份而不是等號進行比較,因此它不能替代假設的'AtomicFloat'。 – 2011-04-05 23:58:38
這將是可怕的低效率實施(但它是可能的)。本質上來說它根據原子數據類型說話毫無意義,因爲對數據類型的操作是原子操作,而不是數據類型本身(也許你知道它,但只是想澄清這一點)。所有這些東西都會混在一起。在OS中你經常需要它們來管理鎖和信號燈,這就是爲什麼許多處理器都有原子整數指令。對於浮點數通常不會實現,因此它們通過將浮點操作包裝在受信號量保護的塊中(通過原子整數實現)來實現。
在高級別的java中,它自己鎖定浮動並沒有問題(你是對的,他們可能已經實現了它),但爲了提高效率,你必須使用低級別的asm來實現它們,所以它非常實用爲高級java用戶提供了一些利用低級別彙編指令的功能。
事實上,我看到很少有應用程序在原子浮動操作很有用。我偶然發現了它們,但是非常罕見,並且始終有可能重新解決浮點部分沒有發生併發問題。
我也很驚訝沒有內置的解決方案。 用例是獲取由併發線程集合發出的值的浮點和,而不使用內存使用量與值的數量。例如,併發線程是預測引擎,您希望在一個位置監視來自所有預測引擎的預測 - 否 - 真值殘差的總和。同時嘗試添加到一個樸素的計數器會導致計數丟失(與整數計數器完全相同)。
一個ConcurrentLinkedQueue
可以收集這些值來概括,但除非有一個專門爲減少排隊的線程(持續運行result += q.poll()
直到poll返回null
,然後q.add(result)
並稍等片刻它再次填滿)的大小隊列將增長到總和值的數量。
Java 8擁有DoubleAdder
和Guava擁有AtomicDouble
(請參閱其他問題的評論),但這不會幫助圖書館開發人員以最小的依賴關係爲目標定位舊的Java。我看了一個DoubleAdder code和AtomicDouble code的樣本,我發現我感到驚訝:他們只是重試加入,然後是compareAndSet
,直到這樣做不是錯誤的。嘗試寫入的線程數量在爭用時可能會增加,但除非它們處於完美的鎖定步驟中,否則有些將贏得比賽並阻止其他人繼續重試。
這裏是一個Scala實現他們做了什麼:
class AtomicDouble {
private val value = new AtomicReference(java.lang.Double.valueOf(0.0))
@tailrec
final def getAndAdd(delta: Double): Double = {
val currentValue = value.get
val newValue = java.lang.Double.valueOf(currentValue.doubleValue + delta)
if (value.compareAndSet(currentValue, newValue))
currentValue.doubleValue
else
getAndAdd(delta) // try, try again
}
}
和嘗試的Java翻譯:
class AtomicDouble {
private AtomicReference<Double> value = new AtomicReference(Double.valueOf(0.0));
double getAndAdd(double delta) {
while (true) {
Double currentValue = value.get();
Double newValue = Double.valueOf(currentValue.doubleValue() + delta);
if (value.compareAndSet(currentValue, newValue))
return currentValue.doubleValue();
}
}
}
它的工作原理(斯卡拉版本數以百計的線程測試),並提供了一種概括爲Double
。
但是,我沒有看到任何理由,爲什麼這會比只寫同步更快或首選。一個阻塞解決方案也會使一些線程等待,而另一些線程則等待增加計數器,但保證所有線程最終都會完成(不依賴於不完善的時間)並且不會浪費CPU(不計算總和,直到您知道允許更新它)。那麼爲什麼要這樣做?
同步是非常昂貴的。在暫停和喚醒線程所需的時間內,您可以在while循環中運行代碼幾千次。 – TomWolk 2017-06-30 13:03:56
這不是一個java問題,所有的語言都受到這個問題的困擾。
彙編指令其原子比較和交換操作編譯到是變種:http://x86.renejeschke.de/html/file_module_x86_id_41.html
這些都對整數操作和FPU的流水線特性使得它更難實施花車/雙打。
雖然這裏的一些答案一些實現沒有提供一個完整和完整的一個。
這一個是。它是AtomicDouble而不是AtomicFloat,因爲它比float更精確。
由於一些張貼在這裏實現,包括他們缺乏更新功能的谷歌番石榴,所以如操作:
average.set(average.get() > x ? dosomething(y) : y) ;
不能進行充分的原子。這一個允許你做:
average.updateAndGet(new DoubleUnaryOperator() {
@Override
public double applyAsDouble(double previous) {
return previous > x ? dosomething(y) : y;
}
});
全面實施下面同樣的方法,發現的AtomicLong:
import static java.lang.Double.doubleToLongBits;
import static java.lang.Double.longBitsToDouble;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleUnaryOperator;
public final class AtomicDouble extends Number {
private static final long serialVersionUID = 12327722191124184L;
private final AtomicLong bits;
public AtomicDouble() {
this(0.0d);
}
public AtomicDouble(double initialValue) {
bits = new AtomicLong(toLong(initialValue));
}
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(double expect, double update) {
return bits.compareAndSet(toLong(expect), toLong(update));
}
/**
* Sets to the given value.
*
* @param newValue the new value
*/
public final void set(double newValue) {
bits.set(toLong(newValue));
}
public final double get() {
return toDouble(bits.get());
}
/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final double getAndSet(double newValue) {
return toDouble(bits.getAndSet(toLong(newValue)));
}
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* <p><a href="package-summary.html#weakCompareAndSet">May fail
* spuriously and does not provide ordering guarantees</a>, so is
* only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful
*/
public final boolean weakCompareAndSet(double expect, double update) {
return bits.weakCompareAndSet(toLong(expect), toLong(update));
}
/**
* Atomically updates the current value with the results of
* applying the given function to the current and given values,
* returning the updated value. The function should be
* side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function
* is applied with the current value as its first argument,
* and the given update as the second argument.
*
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the updated value
* @since 1.8
*/
public final double accumulateAndGet(double x, DoubleBinaryOperator accumulatorFunction) {
double prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsDouble(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
/**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the updated value
*/
public final double addAndGet(double delta) {
return toDouble(bits.addAndGet(toLong(delta)));
}
/**
* Atomically decrements by one the current value.
*
* @return the updated value
*/
public final double decrementAndGet() {
return addAndGet(-1.0d);
}
/**
* Atomically updates the current value with the results of
* applying the given function to the current and given values,
* returning the previous value. The function should be
* side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function
* is applied with the current value as its first argument,
* and the given update as the second argument.
*
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the previous value
* @since 1.8
*/
public final double getAndAccumulate(double x, DoubleBinaryOperator accumulatorFunction) {
double prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsDouble(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the previous value
*/
public final double getAndAdd(double delta) {
return toDouble(bits.getAndAdd(toLong(delta)));
}
public final double getAndDecrement() {
return getAndAdd(-1.0d);
}
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final double getAndIncrement() {
return getAndAdd(1.0d);
}
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final double incrementAndGet() {
return addAndGet(1.0d);
}
/**
* Atomically updates the current value with the results of
* applying the given function, returning the previous value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param updateFunction a side-effect-free function
* @return the previous value
* @since 1.8
*/
public final double getAndUpdate(DoubleUnaryOperator updateFunction) {
double prev, next;
do {
prev = get();
next = updateFunction.applyAsDouble(prev);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* Eventually sets to the given value.
*
* @param newValue the new value
* @since 1.6
*/
public final void lazySet(double newValue) {
bits.lazySet(toLong(newValue));
// unsafe.putOrderedLong(this, valueOffset, newValue);
}
/**
* Returns the value of this {@code AtomicLong} as a {@code long}.
*/
public long longValue() {
return (long) get();
}
/**
* Returns the String representation of the current value.
*
* @return the String representation of the current value
*/
public String toString() {
return Double.toString(get());
}
/**
* Atomically updates the current value with the results of
* applying the given function, returning the updated value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param updateFunction a side-effect-free function
* @return the updated value
* @since 1.8
*/
public final double updateAndGet(DoubleUnaryOperator updateFunction) {
double prev, next;
do {
prev = get();
next = updateFunction.applyAsDouble(prev);
} while (!compareAndSet(prev, next));
return next;
}
/**
* Returns the value of this {@code AtomicLong} as an {@code int}
* after a narrowing primitive conversion.
*
* @jls 5.1.3 Narrowing Primitive Conversions
*/
public int intValue() {
return (int) get();
}
/**
* Returns the value of this {@code AtomicLong} as a {@code float}
* after a widening primitive conversion.
*
* @jls 5.1.2 Widening Primitive Conversions
*/
public float floatValue() {
return (float) get();
}
/**
* Returns the value of this {@code AtomicLong} as a {@code double}
* after a widening primitive conversion.
*
* @jls 5.1.2 Widening Primitive Conversions
*/
public double doubleValue() {
return get();
}
private static double toDouble(long l) {
return longBitsToDouble(l);
}
private static long toLong(double delta) {
return doubleToLongBits(delta);
}
}
- 1. Java/Ruby:有沒有辦法在Java中執行.constantize或Object.send()?
- 2. 有沒有辦法迭代或複製Java ThreadLocal的所有值?
- 3. Android沒有Java
- 4. 有沒有session.save或session.update
- 5. 有沒有在Java中
- 6. 有沒有其他的BeanShell?像JavaScript或Groovy控制檯的Java?
- 7. 有沒有確定是否「主要」是Android或Java的
- 8. 有沒有開源的Java反射工具或罐子?
- 9. Java和XML:讀有或沒有命名空間的XML標記
- 10. 有沒有辦法在Python或Java中輸出關鍵字?
- 11. gmt或沒有gmt
- 12. 運行java進程沒有贏7進入standy或休眠或
- 13. 僞代碼中的MD5或SHA-1或沒有庫的java
- 14. 編程決定Java或.NET,數據庫或沒有數據庫
- 15. PCRE匹配的URL有或沒有ARGS
- 16. 有沒有'git sed'或等價物?
- 17. MSpec更好有或沒有nunit?
- 18. 學習nhibernate(有或沒有流利)
- 19. 檢查元素有子女或沒有
- 20. 有或沒有存儲庫的NHibernate
- 21. CakePHP有沒有app_fixture.php或行爲?
- 22. jquery有或沒有extend關鍵字
- 23. Rails 3路線有或沒有:id
- 24. Android mediaPlayer - 有沒有「isPrepared()」或「getStatus()」方法?
- 25. 有沒有辦法做或jQuery選擇
- 26. NSUSERDefaults類有問題或沒有?
- 27. 有沒有std :: to_u16string或std :: to_u32string?
- 28. 有沒有ISNULL或學說IFNULL函數?
- 29. ADT在C - 有或沒有指針?
- 30. Magento擴展 - 有用或沒有
沒有一個。你的用例是什麼? – 2011-03-31 19:50:15
在Java 8中添加[DoubleAdder](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/DoubleAdder.html)可能符合您的需求。 – kuporific 2014-09-17 21:50:39