1. 代码如下:
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerTest {
final AtomicInteger startPosition = new AtomicInteger(0);
final AtomicInteger wrotePosition = new AtomicInteger(0);
final AtomicInteger committedPosition = new AtomicInteger(0);
final AtomicInteger flushedPosition = new AtomicInteger(0);
public static void main(String[] args) throws Exception {
List<AtomicIntegerTest> list = new LinkedList<>();
for (int i = 0; i < 1000000; i++) {
list.add(new AtomicIntegerTest());
}
System.out.println("create instances 1000000");
System.in.read();
}
}
使用profiler 分析内存如下:
从上图可以看出来AtomicInteger 大概占用了64M。而AtomicIntegerTest对象实例整个占用了96M.
2. 修改之后代码如下:
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicIntegerFieldUpdaterTest {
public static final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> startPosition = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class,"startPositionInt");
public static final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> wrotePosition = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class,"wrotePositionInt");
public static final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> committedPosition = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class,"committedPositionInt");
public static final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> flushedPosition =AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class,"flushedPositionInt");
private volatile int startPositionInt = 0;
private volatile int wrotePositionInt = 0;
private volatile int committedPositionInt = 0;
private volatile int flushedPositionInt = 0;
public static void main(String[] args) throws Exception{
List<AtomicIntegerFieldUpdaterTest> list = new LinkedList<>();
for (int i = 0; i < 1000000; i++) {
list.add(new AtomicIntegerFieldUpdaterTest());
}
System.out.println("create instances 1000000");
System.in.read();
}
}
使用profiler 分析内存如下:
AtomicIntegerFieldUpdaterTest整个对象大小的和为32M,相比之前的总共小了64M。大大的减少了内存的开销。
AtomicIntegerFieldUpdater如何使用
AtomicIntegerFieldUpdater必须是静态变量
被更新的变量必须被关键字volatile修饰
public class AtomicIntegerFieldUpdaterTest {
public static final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> startPosition = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class,"startPositionInt");
private volatile int startPositionInt = 0;
}
4. 使用AtomicIntegerFieldUpdater后内存为什么会减少
代码如下:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
class FieldUpdaterTest {
public volatile int a = 0;
private static final AtomicIntegerFieldUpdater updater = AtomicIntegerFieldUpdater.newUpdater(FieldUpdaterTest.class, "a");
}
class AtomicTest22 {
public volatile int a = 0;
private AtomicInteger atomicInteger = new AtomicInteger(0);
}
public class T {
public static void main(String[] args) {
FieldUpdaterTest test = new FieldUpdaterTest();
System.out.println(ClassLayout.parseInstance(test).toPrintable());
AtomicTest22 test2 = new AtomicTest22();
System.out.println(ClassLayout.parseInstance(test2).toPrintable());
}
}
结果如下:
org.example.jucdemo2.atomic.FieldUpdaterTest object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0x01001200
12 4 int FieldUpdaterTest.a 0
`Instance size: 16 bytes`
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
org.example.jucdemo2.atomic.AtomicTest22 object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0x0101f0a8
12 4 int AtomicTest22.a 0
16 4 java.util.concurrent.atomic.AtomicInteger AtomicTest22.atomicInteger (object)
20 4 (object alignment gap)
`Instance size: 24 bytes`
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
可以看到,FieldUpdaterTest比AtomicTest少了8 bytes。仔细分析上图结果,我们发现后者比前者多了4 bytes 大小的AtomicInteger对象,这也正是AtomicInteger中的成员变量int value,而AtomicIntegerFieldUpdater是staic final类型,即类变量,并不会占用当前对象的内存。正是基于AtomicIntegerFieldUpdater该使用特性,当字段所属的类会被创建大量的实例时,如果用AtomicInteger每个实例里面都要创建AtomicInteger对象,从而多出很多不必要的内存消耗。