天天看点

JAVA中的原子操作类

多线程情况下,要保证操作数据的原子性,

原子性:就是不能再往下细分的操作,JAVA 的原子操作的原理 主要是利用了CAS原理,限于篇幅 建议移步 大神的关于CAS原理的文章

以为为类操作的API和相关注释,直接上源码

原子更新基本类型类:

package com.hhx.offline_tools.encode.Atomic;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 原子更新基本类型类
 * 
 * 1、AtomicBoolean 原子更新布尔类型值
 * 2、AtomicInteger 原子更新整型
 * 3、AtomicLong    原子更新 长整型
 * @author 清水贤人
 *
 */
public class AtomicBaseType {

	// 原子方式更新基本类型,Atomic 包提供以下3个类
	static AtomicInteger aInteger = new AtomicInteger(1);     //写1 代表默认值为1
	static AtomicBoolean aBoolean = new AtomicBoolean();  //括号中可以自定义默认值,不定义默认为false
	static AtomicLong    aLong    = new AtomicLong();         //默认值为0
	
	public static void main(String[] args) {
		 /**
		  * AtomicInteger API 
		  * get()是获取当前的值
		  * addAndGet(X)是以原子方式将输入的值与实例中的值相加 并返回结果
		  * compareAndSet(x,y)先获取当前的值,如果输入的x值和当前值相等,则吧当前值变为y,否则保持不变
		  * getAndIncrement 以原子方式将当前值加1,同时返回加1之前的值
		  * decrementAndGet 以原子形式减去1 并返回减1之后的值
		  * getAndSet(x) 以原子方式设置值为x 并返回原始值
		  */
		System.out.println(aInteger.get());
		System.out.println(aInteger.addAndGet(1));
		System.out.println(aInteger.compareAndSet(1, 5));
		System.out.println(aInteger.getAndIncrement());
		System.out.println(aInteger.decrementAndGet());
		System.out.println(aInteger.getAndSet(8));
		System.out.println(aInteger.get());
		
		
		//由于 AtomicBoolean,AtomicLong API和AtomicInteger 相差无几 在这里不列出
		 
	}

}
           

原子更新数组类型类:

/**
 * 
 */
package com.hhx.offline_tools.encode.Atomic;

import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.atomic.AtomicReferenceArray;

/**
 * 原子更新数组类型类
 * 
 * 1、AtomicIntegerArray     原子更新整数类型里的元素
 * 2、AtomicLongArray        原子更新长整型数组里的元素
 * 3、AtomicReferenceArray   原子更新引用类型数组里的元素
 * @author 清水贤人
 *
 */
public class AtomicArrayType {
	
	// 定义数组
	static int[] value = new int[] { 7, 2 };

	// 原子更新整数类型里 的元素,这里的value 复制时吧里面的两个元素给初始化到这个数组
	static AtomicIntegerArray integerArray = new AtomicIntegerArray(value);
	
	// 原子更新长整形类型数组里的内容
	static AtomicLongArray longArray = new AtomicLongArray(0);
	
	//原子更新引用类型数组里的元素
	static AtomicReferenceArray referenceArray = new AtomicReferenceArray(0);
	
	public static void main(String[] args) {
		
		//integerArray.getAndSet(0, 8);// 获取数组的第0个元素 并赋值为8
		
		//System.out.println(integerArray.get(0)); // 这个是获取修改后的值 为8
		
		/**
		 * 数组value 通过构造方法传递进去,
		 * 然后AtomicIntegerArray 会将当前的数组复制一份,
		 * 所以当AtomicIntegerArray对内部元素进行修改的时候
		 * 不会影响传入的数组
		 */
		//System.out.println(value[0]); // 原始数组的值不变 得到的依旧是7
		
		/**
		 * addAndGet 方法
		 * 第一个入参是 数组中的元素位置(i)
		 * 第二个元素是 准备要加的值(即加数)
		 * 运行后的结果 的返回值就是 数组中的 i和加数的 加法运算值
		 */
		//System.out.println(integerArray.addAndGet(0, 2));
		
		/**
		 * compareAndSe 方法的返回值是boolean
		 * 第一个参数的是数组的下标
		 * 第二个参数是期望的元素的指定下标的值
		 * 第三个参数 如果准备修改为的值
		 * 
		 * 如果第二个元素和数组下标指定的元素的值 相等,则将该小标的值修改为第三个参数的值,返回true
		 * 反之,不做任何修改 返货false
		 */
		//System.out.println(integerArray.compareAndSet(0, 7, 9));
		
		/**
		 * 对指定数组下标的元素进行加1 操作
		 */
		System.out.println(integerArray.incrementAndGet(0));
		 
		// 其余的和AtomicIntegerArray 相差无几 不在列出
	}
	
	 
	
	
}
           

原子更新字段类:

/**
 * 
 */
package com.hhx.offline_tools.encode.Atomic;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

import org.omg.CORBA.ObjectHolder;

/**
 * 原子更新字段类
 * 类为:
 * 1、AtomicIntegerFieldUpdater 原子更新整形的字段的更新器
 * 2、AtomicLongFieldUpdater    原子更新长整形字段的更新器
 * 3、AtomicStampedReference    原子更新带有版本号的引用类型
 * @author 清水贤人
 *
 */
public class AtomicFieldType {
	
	
	 

	/**
	 * 创建原子更新器,并设置需要更新的对象类和对象的属性
	 * 
	 * 原子更新字段需要两部:
	 * 1、因为原子更新字段都是抽象类,每次使用的时候,必须使用静态方法NewUpdater(),创建一个更新器
	 * 并且需要设置需要更新的类和属性
	 * 2、更新字段,字段必须使用public volatile修饰
	 */
	private static AtomicIntegerFieldUpdater<User> atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.
			newUpdater(User.class, "old");
	
	public static void main(String[] args) {
		
		User user = new User("hhx", 8);
		
		// 增整了1 但是会输出旧的值
		System.out.println(atomicIntegerFieldUpdater.getAndIncrement(user));
		
		// 直接输出新值(增长后的)
		System.out.println(atomicIntegerFieldUpdater.get(user));
	}
			
			
	
	
	
	
	// User 实体
	public static class User {
		
		private String name;
		public volatile int old;
	    volatile Integer sex=3;
		
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getOld() {
			return old;
		}
		public void setOld(int old) {
			this.old = old;
		}
		public User(String name, int old) {
			super();
			this.name = name;
			this.old = old;
		}
	}
}
           

原子更新引用类型:

/**
 * 
 */
package com.hhx.offline_tools.encode.Atomic;

import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * 
 * 原子更新引用类型
 * 
 * 1、AtomicReference               原子更新引用或类型的字段
 * 2、AtomicReferenceFieldUpdater   原子更新带有引用类型的字段
 * 3、AtomicMarkableReference       原子更新带有标记位的引用类型
 * 
 * @author 清水贤人
 *
 */
public class AtomicReferType {
	
	public static AtomicReference<User> atomicUser = new AtomicReference<User>();
	
	
	public static void main(String[] args) {
		
		User user = new User("hhx" , 8);
		
		atomicUser.set(user);
		
		User updateUser = new User("hhx1" , 81);
		
		/**
		 * compareAndSet
		 * 这两个方法 目前是一样的,但是源码的注释不一样
		 * 老外给的解释是:我们暴保留后期会更改的权利,只不过暂时没有变
		 * 建议分开使用
		 */
		System.out.println(atomicUser.compareAndSet(user, updateUser));
		System.out.println(atomicUser.weakCompareAndSet(user, updateUser));
		
		/**
		 * AtomicReferenceFieldUpdater 
		 * 他能对指定类的指定volatile字段进行原子更新(不能声明为private)
		 * 第一个参数为要更新的类的类名
		 * 第二个字段为要更新的字段名属性(包装类)
		 * 第三个字段为要更新的字段的 字段名(用双引号包裹)
		 */
		AtomicReferenceFieldUpdater fileUpload = AtomicReferenceFieldUpdater.
				                                 newUpdater(User.class, Integer.class, "sex");
		
		fileUpload.compareAndSet(user, user.sex, 6);
		
		System.out.println(user.sex);
		
	}
	
	
	 


	// User 实体
	static class User {
		
		private String name;
		private int old;
	    volatile Integer sex=3;
		
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getOld() {
			return old;
		}
		public void setOld(int old) {
			this.old = old;
		}
		public User(String name, int old) {
			super();
			this.name = name;
			this.old = old;
		}
		
		
	}

}
           

继续阅读