併發原子類

1.8新增的原子類
            DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64

1 原子更新基本類型
        發展至JDk1.8,基本類型原子類有以下幾個:
            AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、
            LongAccumulator、LongAdder
        大致可以歸爲3類
            AtomicBoolean、AtomicInteger、AtomicLong  元老級的原子更新,方法幾乎一模一樣
            DoubleAdder、LongAdder  對Double、Long的原子更新性能進行優化提升
            DoubleAccumulator、LongAccumulator  支持自定義運算

2 原子更新數組類型
        AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

3 原子地更新屬性

        原子地更新某個類裏的某個字段時,就需要使用原子更新字段類,Atomic包提供了以下4個類進行原子字段更新
        AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater

        使用上述類的時候,必須遵循以下原則
        字段必須是volatile類型的,在線程之間共享變量時保證立即可見
        字段的描述類型是與調用者與操作對象字段的關係一致。
        也就是說調用者能夠直接操作對象字段,那麼就可以反射進行原子操作。
        對於父類的字段,子類是不能直接操作的,儘管子類可以訪問父類的字段。
        只能是實例變量,不能是類變量,也就是說不能加static關鍵字。
        只能是可修改變量,不能使final變量,因爲final的語義就是不可修改。
        對於AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long類型的字段,不能修改其包裝類型               (Integer/Long)。
        如果要修改包裝類型就需要使用AtomicReferenceFieldUpdater。

4 原子更新引用
        AtomicReference:用於對引用的原子更新
        AtomicMarkableReference:帶版本戳的原子引用類型,版本戳爲boolean類型。
        AtomicStampedReference:帶版本戳的原子引用類型,版本戳爲int類型。

Demo:

/**
 * - AtomicInteger Demo
 * @author 
 * @date 
 */
public class Demo1 {

	private static AtomicInteger sum = new AtomicInteger(0);
	
	public static void inCreate() {
		sum.incrementAndGet();
	}
	
	public static void main(String[] args) {
		
		for (int i = 0; i < 10; i++) {
			
			new Thread(() -> {
				for (int j = 0; j < 100; j++) {
					inCreate();
					System.out.println(sum);
				}
			}).start();
						
		}
		
	}
	
}
/**
	 * - 輸入一個數字,如果比上一個大,則返回當前,反之,則返回上一個.
	 * @param args  
	 * @author: 
	 * @date: 
	 */
	public static void main(String[] args) {
		
		// 第一個參數是一個 運算或者比較函數, 第二個是 第一個函數的初始值.
		//LongAccumulator la = new LongAccumulator((left, right) -> left > right ? left : right, 4L);
		LongAccumulator la = new LongAccumulator((left, right) -> left * right, 4L);
		
		// 傳入 參數進去 與 初始值 運算 或者比較.
		la.accumulate(5L);
		System.out.println(la.get());
		
		la.accumulate(4L);
		System.out.println(la.get());
		
		la.accumulate(3L);
		System.out.println(la.get());
		
	}
		
}
public class AtomicIntegerArrayDemo {

	public static void main(String[] args) {
		
		int[] arr = new int[] {2,4,0};
		
		AtomicIntegerArray aia = new AtomicIntegerArray(arr);
		
		aia.set(2, aia.addAndGet(0, 8));
		
		/*for (int i = 0; i < aia.length(); i++) {
			System.out.println(aia.get(i)); //aia [10,4,10] 原數組 arr 不受影響.
		}*/
		
		aia.accumulateAndGet(1, 5, (x, y) -> x * y);
		for (int i = 0; i < aia.length(); i++) {
			System.out.println(aia.get(i)); //aia [10,20,10] 
		}
		
	}
		
}
public class AtomicLongFieldUpdaterDemo {

	public static void main(String[] args) {

		AtomicLongFieldUpdater<Student> au = AtomicLongFieldUpdater.newUpdater(Student.class, "id");
		
		Student student = new Student(3L, "zhansan");
		
		au.compareAndSet(student, 3L, 100L);
		
		au.accumulateAndGet(student, 35L, (x, y) -> x + y);
		
		AtomicReferenceFieldUpdater<Student, String> arfu = AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class, "name");
		
		arfu.set(student, "lisi");
		// arfu.compareAndSet(student, "zhansan", "wangwu");  // 這句會更新失敗. name 已經不是"張三"
		arfu.compareAndSet(student, "lisi", "wangwu");
		System.out.println(student.toString());
	}

}

/*
 *   注意:
 *   1. 要修改的字段必須是 volatile 類型.
 *   2. Integer 和 Long 只能 修改 int 和 long 基本類型,而不能修改包裝類型.  volatile long id;  volatile Long id;
 *   	如果要修改包裝類型,用 AtomicReferenceFieldUpdater
 *   3. 不能操作 父類字段.
 */

class Student {

	volatile long id;
	volatile String name;

	public Student(Long id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}

	public final Long getId() {
		return id;
	}

	public final void setId(Long id) {
		this.id = id;
	}

	public final String getName() {
		return name;
	}

	public final void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}

}

---end.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章