[Java]初识AtomicInteger

AtomicInteger,这是java提供的一个原子操作Integer的类,这在我眼里还是一个稀客,可能是不怎么感兴趣,以至于一直当作简单的volatile,这也是我的拙见。其实这家伙还是挺好用的,在常见的场景中,如count++或++count,这在java多线程的使用中是不安全的,而AtomicInteger属于原子操作(线程安全),可以在下面的例子中看出来。

package org.jan.java.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 关于count++在多线程调用情况下
 *
 * @author jan
 */
public class Counter {
	private volatile int count = 0;

	/**
	 * 为了保证数据的准确性,多线程的情况下需要加上synchronized关键字</br>
	 * 否则会出现出乎预料的结果 这也是线程安全的重要体现
	 */
	public void increment() {
		count++;
	}

	private int getCount() {
		return count;
	}

	/**
	 * 这里模拟一个递增的任务,递增目标为100W
	 */
	public static void main(String[] args) throws InterruptedException {
		 final Counter counter = new Counter();
//		final AtomicCounter counter = new AtomicCounter();
		int workCount = 1000000;
		ExecutorService executor = Executors.newFixedThreadPool(10);
		long start = System.currentTimeMillis();
		for (int i = 0; i < workCount; i++) {
			Runnable runnable = new Runnable() {
				@Override
				public void run() {
					counter.increment();
				}
			};
			executor.execute(runnable);
		}
		// 关闭启动线程,执行未完成的任务
		executor.shutdown();
		// 等待所有线程完成任务,完成后才继续执行下一步
		executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
		System.out.println("耗时:" + (System.currentTimeMillis() - start) + "ms");
		System.out.println("执行结果:count=" + counter.getCount());
	}
}

它的结果不是我们预料的100 0000 .通常我们需要加上在count++时 加上synchronized关键字,保证他的正确性。

如果我们换个方式,用AtomicInteger来替换count++,怎么做呢?

public class AtomicCounter {
	private AtomicInteger count = new AtomicInteger(0);

	// 使用AtomicInteger之后,不需要加锁,也可以实现线程安全。
	public void increment() {
		//获取当前的值并自增
		count.incrementAndGet();
	}
	/**
	 * 获取当前的值
	 * @return
	 */
	public int getCount() {
		return count.get();
	}
	//递减
	public void deIncrement(){
		count.decrementAndGet();
	}
}

把最开始的代码里的Counter对象换成我们的AtomicCounter类的对象,试试他的方法,我们发现,结果就保证了100W!

AtomicInteger 还有其他的一些方法,查一下Api就行了。而且也不是说只有Integer有这么个原子操作的类,这里不是重点,有兴趣就自己百度去吧。

//获取当前的值
publicfinal int get()

//取当前的值,并设置新的值
 publicfinal int getAndSet(intnewValue)

//获取当前的值,并自增
 publicfinal int getAndIncrement()

//获取当前的值,并自减
publicfinal int getAndDecrement()

//获取当前的值,并加上预期的值
publicfinal int getAndAdd(intdelta)

你说他就这么一个特点,并不是很吸引人?

他的性能貌似也挺给力的,就如最开始的那个代码把,我看了一下啊,在count++ 方法加上synchronized字段后与 atomicInteger的increment方法相比较,atomicInteger的性能貌似比前者更快!有兴趣的可以自己比较一下看看。

嗯。

最后,感谢以下博文的鼎立奉献,感谢百度祖师爷的全力帮助

  1. http://my.oschina.net/i33/blog/50503
  2. http://blog.csdn.net/zz198808/article/details/8029405

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-10 02:09:07

[Java]初识AtomicInteger的相关文章

JAVA 初识类加载机制 第13节

JAVA 初识类加载机制 第13节 从这章开始,我们就进入虚拟机类加载机制的学习了.那么什么是类加载呢?当我们写完一个Java类的时候,并不是直接就可以运行的,它还要编译成.class文件,再由虚拟机解释给当前的操作系统去执行.这些过程都是我们看不见的,我们能看见的也就是一个.class文件.既然虚拟机要解释这些.class文件给当前的操作系统听,那么他怎么获得这些.class文件呢?虚拟机获得这些.class文件的过程就是类加载了. 所以,总结来说就是:虚拟机将.class文件从磁盘或者其他地

java中AtomicInteger的使用

AtomicInteger,命名带有Atomic,很明显本身是原子性.这个类常是线程安全,多用于高并发对数据的修改.关于多线程原子性,也顺带回顾下可见性原子性原子性具有不可分割的特性.原子操作,具有原子性.比如 i=0属于原子操作,再比如i++,实际是i = i + 1,是可分割的,属于非原子操作.非原子操作不是线程安全,在多线程中经常使用sychronized同步成原子操作.AtomicInteger.AtomicLong等是原子操作,在java.util.concurrent.atomic下

Java学习日记:Week1---day1-2 Java初识

前言: 新的旅程正式开始了,经过了两周的c语言预科班学习,对程序的开发有了第一步的认知.如今Java课程也如期开始,对于一个程序员究竟是先学习哪个语言好已经没有必要去探究了,如今既然上了Java的船自然要老老实实的走,能到什么程度就看自己了,个人对自己还是有点信心的. 课从昨天就正式开始了,昨天老师讲了一天大方面的东西,总之没什么具体内容,今天开始了初始java的第一课:简单理了理今天老师讲的内容,挑了一些重点的记在日记. 一.JAVA的版本以及JDK 1)Java的几个版本 java SE(j

Java初识

Java的标准输入与输出:输出: System.out.print(); System.out.println(); //多打印了一个回车 System.out.println("小刘刘"); System.out.println("小王王"); 输入: import java.util.Scanner; Scanner scanner = new Scanner(System.in);//输入对象 scanner.close();//关闭scanner scann

第一节:Java初识与计算机基础

一.计算机 = 硬件 + 软件 1.硬件:计算机中看的见摸得着的物理元件,例如:CPU(中央处理器).内存条.硬盘... CPU:计算机的运算和控制核心,主要用于对数据的逻辑运算以及对计算机指令的解析执行,相当于人类的大脑. 内存条:用于存储计算机运行时的临时数据,是硬盘加载数据进入cpu处理的临时存放区(内存小,读取速度快,断电或关闭程序时数据丢失) 硬盘:用于长期保存用户数据(内存大,读取速度相对慢,数据长期保存) 存储器读取速度比较:寄存器(cpu内) > 内存条 > 硬盘(固态硬盘  

java初识集合(list,set,map)

java的集合有三类:list,set,map.list和set继承了collection接口.区别(list可以添加重复对象,且按照索引位置排序:set没有这两种特点). map是通过key操作里面的value,操作的是成对的对象.put放入对象,get取出对象. 另外:colletion没有随机访问的get()方法,因为collection还包括set,而set有自己的内部顺序.所以,要检查collection元素,必须使用iterator对象. 1.list中有ArrayList(类似数组

菜鸟之路-java初识

学习java前需要了解的基础计算机知识 1.软件:按照特定顺序组织一系列计算机数据和指令的集合:分为系统软件和应用软件: 软件开发就是制作软件: 2.人机交互:软件使人和计算机的交互更加便利:交互方式:图形化界面和命令行方式: 3.命令行方式:dir 目录下的所有文件和文件夹 md  创建新目录 rd 删除目录 cd   进入指定目录 cd.. 返回上一级目录 cd\   返回主目录 del  删除目录 exit   退出命令行 java的概述 1.是sun公司1995年推出的一款高级编程语言,

java 初识String

   String 类是final类,不能被继承. String 类代表字符串.Java程序中的所有字符串字面值作为此类的实例实现. 字符串是常量:它们的值在创建之后不能更改.字符串缓冲区支持可变的字符串.因为 String 对象是不可变的,所以可以共享. Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持.字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的.字符串转换是通过 toString 方法

Java学习(一)---Java初识

一.Java介绍 关于Java的诞生和发展网上比较多,在此就不再赘述了,可以参考http://i.cnblogs.com/EditArticles.aspx?postid=4050233. 1.1 Java的开发平台JDK 1.1.1 JDK 1.0----JRE+JDK 1995年,Sun虽然推出了Java,但这只是一种语言,如果想开发复杂的应用程序,必须要有一个强大的开发类库.因此,Sun在1996年初发布了JDK 1.0.这是Sun公司发布的第一版JDK,这个版本包括两部分: JRE 运行