博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 学习笔记之AtomicInteger类的使用
阅读量:5095 次
发布时间:2019-06-13

本文共 2315 字,大约阅读时间需要 7 分钟。

今天在看源码的时候看到了一个类叫AtomicInteger,所以决定探索一番。

从源码中看出,AtomicInteger继承自Number类,值得注意的是其中的value属性是用volatile关键字修饰的,这个关键字在java 1.5之前经常容易引发一些意想不到的错误,之后得到了优化,才得以重生。这里先简单的说下volatile关键字吧,被其修饰的变量当线程前来访问的时候,会去读取该变量被修改后的值,从而达到维持有序性的目的。volatile有两个有两个特性,被其修饰的变量对所有线程可见,另一个则是禁止了指令的重排序优化。至于对volatile关键字具体分析要放到另外的篇幅里面了。

下面回到AtomicIntger类,举几个例子来表明其用处。

package test;public class Test1 {	static int num;	static boolean flag;	public static void main(String[] args) {		Thread t1 = getThread();		t1.start();		Thread t2 = getThread();		t2.start();		while (true) {			if(!t1.isAlive() && !t2.isAlive()){				System.out.println("最终计算结果为:" + num);				break;			}		}	}	public static Thread getThread() {		return new Thread(new Runnable() {			@Override			public void run() {				for (int i = 0; i < 10000; i++) {					num++;				}				Thread.yield();			}		});	}}

这是一个简单多线程同时对一个变量进行操作的例子,我们可以在控制台看到如下打印:

从系统打印可以看出,因为同一个数据被多个线程同时操作,并且没有做任何处理,从而导致了程序错误。传统的解决方法是在操作处加上synchronized关键字从而避免并发线程同时访问,代码如下:

 

package test;public class Test1 {	static int num;	static boolean flag;	public static void main(String[] args) {		Thread t1 = getThread();		t1.start();		Thread t2 = getThread();		t2.start();		while (true) {			if(!t1.isAlive() && !t2.isAlive()){				System.out.println("最终计算结果为:" + num);				break;			}		}	}	public static Thread getThread() {		return new Thread(new Runnable() {			@Override			public void run() {				synchronized (Test1.class) {					for (int i = 0; i < 10000; i++) {						num++;					}				}				Thread.yield();			}		});	}}

 

执行上述代码可以看到如下打印:

下面将尝试使用AtomicInteger来取代使用synchronized关键字的使用,代码如下:

 

package test;import java.util.concurrent.atomic.AtomicInteger;public class Test1 {	static AtomicInteger ato = new AtomicInteger(0);	static boolean flag;	public static void main(String[] args) {		Thread t1 = getThread();		t1.start();		Thread t2 = getThread();		t2.start();		while (true) {			if(!t1.isAlive() && !t2.isAlive()){				System.out.println("最终计算结果为:" + ato.get());				break;			}		}	}	public static Thread getThread() {		return new Thread(new Runnable() {			@Override			public void run() {				for (int i = 0; i < 10000; i++) {					ato.incrementAndGet();				}				Thread.yield();			}		});	}}

控制台输出如下:

 

由此可见,AtomicInteger是可以线程安全的进行加减操作,非常适合高并发的情况。但因为其内部使用了volatile关键字,使得jvm的一些优化功能被停用了,所以还是需要根据实际场景来使用。

 
 
 
 
 
 
 
 
 
 

转载于:https://www.cnblogs.com/moonfish1994/p/10222429.html

你可能感兴趣的文章
4H.Applese 的大奖(C++)
查看>>
从运行中启动收索引擎
查看>>
java.sql.Date java.sql.Time java.sql.Timestamp 之比较
查看>>
JavaScript基本语法
查看>>
导出Maven依赖包
查看>>
实验三
查看>>
kubeadm安装k8s集群及dashboard安装(推荐)
查看>>
数据库操作语句
查看>>
Java常见异常
查看>>
XML解析
查看>>
switch处理多分支结构
查看>>
.net使用abot爬虫简单例子
查看>>
直接拿来用!最火的Android开源项目(完结篇)(转)
查看>>
Handler相关
查看>>
【转】关于windows server 2003不能共享问题
查看>>
jsonp的简单实现
查看>>
光电系统显控软件
查看>>
Jquery Mini UI 让我们的项目体验轻便快捷
查看>>
UVA-10608 - Friends
查看>>
没有找到mingwm10.dll的解决办法和mingwm10.dll的作用
查看>>