经常有人提到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来同步。