原子变量
AtomicInteger基本概念
-
AtomicInteger:
- 是一个提供原子操作的Integer类
- 通过线程安全的方式操作加减
-
AtomicInteger使用场景: AtomicInteger提供原子操作来进行Integer的使用,适合高并发的场景
Integer与AtomicInteger的比较
- 在使用Integer的时候,必须加上synchronized锁来保证出现并发线程同时访问的情况
public class IntegerSample {
private static Integer count = 0;
synchronized static void increment() {
count++;
}
}
- 在AtomicInteger中不需要加锁,因为AtomicInteger是提供原子操作的
public class AtomicIntegerSample {
private static AtomicInteger count = new AtomicInteger(0);
static void increment() {
count.getAndIncrement();
}
}
AtomicInteger源码
public class AtomicInteger extends Number implements java.io.Serializable {
private static final serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueoffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception e) {
throw new Error(ex);
}
}
private volatile int value;
...
}
-
value:
-
volatile作用: 使得多个线程可以共享变量
-
volatile的问题: 使用volatile将使得JVM优化失去作用,导致效率降低
AtomicInteger使用实例
- 在多线程的情况下,使用AtomicInteger:
public class AtomicTest {
static long randomTime() {
return (long)(Math.random() * 1000);
}
public static void main(String args[]) {
// 阻塞队列
final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
// 线程池
final ExecutorService exec = Executors.newFixedThreadPool(5);
final File root = new File("D:\\chova");
// 完成标志
final File exitFile = new File("");
/*
* 原子整型 AtomicInteger
* AtomicInteger可以在并发的情况下达到原子化更新,避免使用了synchronized,而且性能非常高
*/
// 读 个数
final AtomicInteger rc = new AtomicInteger();
// 写 个数
final AtomicInteger wc = new AtomicInteger();
// 读线程
Runnable read = new Runnable() {
public void run() {
scanFile(root);
scanFile(exitFile);
}
public void scanFile(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory || pathname.getPath().endsWith(".java");
}
});
for (File one : files) {
scanFile(one);
}
} else {
try {
// 调用AtomicInteger的incrementAndGet(),以原子方式将当前值加1并返回新值
int index = rc.incrementAndGet();
System.out.println("Read:" + index + " " + file.getPath());
// 添加到阻塞队列
queue.put(file);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
// submit方法提交一个Runnable任务用于执行,并返回一个表示该任务的Future
exec.submit(read);
/*
* 四个写线程
*/
for (int index = 0; index < 4; index++) {
// 写线程
final int num = index;
Runnable write = new Runnable() {
String threadName = "Write" + num;
public void run() {
while (true) {
try {
Thread.sleep(randomTime());
// 调用AtomicInteger的incrementAndGet(),以原子方式将当前值加1并返回新值
int index = wc.incrementAndGet();
// 获取并移除此队列的头部,必要时在元素变得可用之前一直保持等待
File file = queue.take();
/*
* 队列中已无对象
*/
if (file = exitFile) {
// 再次添加exitFile标志,以便让其余线程正常退出
queue.put(exitFile);
break;
}
System.out.println(threadName + ":" + index + " " + file.getPath());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
exec.submit(write);
}
exec.shutdown();
}
}
总结
-
AtomicInteger是在使用非阻塞算法时实现并发控制,在一些高并发的场景中非常适用
网友评论