经常有人提到volatile,Atomic类型,给多线程编程提高性能,自己跑下测试结果就知道了…
import java.util.concurrent.atomic.AtomicInteger;
public class Counter {
public static int count=0;
public static volatile int volatileCount = 0;
public static AtomicInteger atomicCount = new AtomicInteger(0);
public static byte[] lock=new byte[0];
public static int syCount=0;
public static void sleep(final int gap){
try {
Thread.sleep(gap);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void incrInt(final int gap){
count++;
sleep(gap);
}
public static void incrVolatileInt(int gap){
volatileCount++;//和volatileCount上一个状态相关,不具于原子性
sleep(gap);
}
public static void incrAtomicInt(final int gap) {
//第一种方式:
//int tmp=atomicCount.get();
//atomicCount.getAndSet(tmp+1);//注意:tmp+1不具原子性
//第二种方式:
atomicCount.getAndIncrement();//具备原子性的
sleep(gap);
}
public static void incrSynInt(final int gap){
synchronized(lock){
syCount++;
sleep(gap);
}
}
public static void testInt(int count,final int gap){
long st=System.currentTimeMillis();
Thread threads[]=new Thread[count];
for (int i = 0; i < count; i++) {
threads[i]=new Thread(new Runnable() {
@Override
public void run() {
Counter.incrInt(gap);
}
});
threads[i].start();
}
for(int i=0;i<count;i++){
try {
threads[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long et=System.currentTimeMillis();
System.out.println("---运行时间="+(et-st));
// 这里每次运行的值都有可能不同,可能为1000
System.out.println("运行结果:Counter.count=" + Counter.count);
}
public static void testVolatileInt(int count,final int gap){
long st=System.currentTimeMillis();
Thread threads[]=new Thread[count];
for (int i = 0; i < count; i++) {
threads[i]=new Thread(new Runnable() {
@Override
public void run() {
Counter.incrVolatileInt(gap);
}
});
threads[i].start();
}
for(int i=0;i<count;i++){
try {
threads[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long et=System.currentTimeMillis();
System.out.println("---运行时间="+(et-st));
System.out.println("运行结果:Counter.volatileCount=" + Counter.volatileCount);
}
public static void testAtomicInt(int count,final int gap){
long st=System.currentTimeMillis();
Thread threads[]=new Thread[count];
for (int i = 0; i < count; i++) {
threads[i]=new Thread(new Runnable() {
@Override
public void run() {
Counter.incrAtomicInt(gap);
}
});
threads[i].start();
}
for(int i=0;i<count;i++){
try {
threads[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long et=System.currentTimeMillis();
System.out.println("---运行时间="+(et-st));
System.out.println("运行结果:Counter.atomicCount=" + Counter.atomicCount.get());
}
public static void testSynInt(int count,final int gap){
long st=System.currentTimeMillis();
Thread threads[]=new Thread[count];
for (int i = 0; i < count; i++) {
threads[i]=new Thread(new Runnable() {
@Override
public void run() {
Counter.incrSynInt(gap);
}
});
threads[i].start();
}
for(int i=0;i<count;i++){
try {
threads[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long et=System.currentTimeMillis();
System.out.println("---运行时间="+(et-st));
System.out.println("运行结果:Counter.syCount=" + Counter.syCount);
}
public static void main(String[] args) {
int cnt=100000;
int gap=2;
testInt(cnt,gap);
System.out.println("-------------------------------------------");
testVolatileInt(cnt,gap);
System.out.println("-------------------------------------------");
testAtomicInt(cnt,gap);
System.out.println("-------------------------------------------");
testSynInt(cnt,gap);
}
}
我输出的打印日志:
---运行时间=4655
运行结果:Counter.count=99999
-------------------------------------------
---运行时间=4536
运行结果:Counter.volatileCount=100000
-------------------------------------------
---运行时间=4626
运行结果:Counter.atomicCount=100000
-------------------------------------------
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:673)
at Counter.testSynInt(Counter.java:136)
at Counter.main(Counter.java:160)
多运行几次会发现结果还时常变化,多线程开发中,如果volatile和volatile之前的值无关才用volatile,因为性能好,不过最好不用,很容易出错的。
Atomic类型最好用它的成员方法,否则请用synchronized来同步。