AtomicBoolean在java.util.concurrent.atomic包下,源代码如下,同样用CAS方法。
AtomicBoolean 可用在应用程序中(如以原子方式更新的标志),但不能用于替换 Boolean。即能够保证在高并发的情况下只有一个线程能够访问这个属性值。
/**
* 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(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
一般情况下,我们使用 AtomicBoolean 高效并发处理 “只初始化一次” 的功能要求:
private static AtomicBoolean initialized = new AtomicBoolean(false);
public void init()
{
if( initialized.compareAndSet(false, true) )//如果为false,更新为true
{
// 这里放置初始化代码....
}
}
如果没有AtomicBoolean,我们可以使用volatile做如下操作:
public static volatile initialized = false;
public void init()
{
if( initialized == false ){
initialized = true;
// 这里初始化代码....
}
}
具体实现代码如下:
package concurrency.example.atomic;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
/*
*Created by William on 2018/4/28 0028
*/
@Slf4j
public class AtomicExample7Boolean {
private static AtomicBoolean isHappened = new AtomicBoolean(false);
public static int clientTotal = 5000;
public static int threadTotal = 200;
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
test();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("isHappened:{}", isHappened.get());
}
public static void test() {
if (isHappened.compareAndSet(false, true)) {
log.info("execute");
}
}
}