java并发相关(3)---Atomic原子类相关

本文介绍了Java中的Atomic原子类,包括AtomicInteger、AtomicLong、AtomicReference及其数组类型,详细阐述了它们的内部原理和主要API,如循环CAS操作,并通过示例展示了AtomicReference在并发栈中的应用。
摘要由CSDN通过智能技术生成

一、AtomicInteger等

Atomic是一系列原子类:
 *  AtomicInteger,AtomicLong,AtomicReference,AtomicIntegerArray...。
 *    内部实现原理是:循环CAS。

public class AtomicBaseDemo {
	
	public static void main(String[] args) throws InterruptedException {
		//一、Api基本使用
		AtomicInteger atomicInt = new AtomicInteger(1);
		int incrementAndGet = atomicInt.incrementAndGet();
		boolean compareAndSet = atomicInt.compareAndSet(3, 11); // 此时预期应该是2
		System.out.println(compareAndSet); // false
		System.out.println(atomicInt.compareAndSet(2, 10)); // true
		System.out.println(atomicInt.get()); // 10
		System.out.println(atomicInt.getAndAdd(10)); // 10,返回10,实际值是20
		System.out.println(atomicInt.getAndSet(5)); // 20, 返回5,实际值是5.
		
		//二、案例
		atomicInt.set(0);
		final int threadSize = 1000;
		Thread[] ts = new Thread[threadSize];
		for (int i = 0; i < threadSize; i++) {
			ts[i] = new Thread() {
				public void run() {
					atomicInt.incrementAndGet();
				}
			};
		}
		for (Thread t : ts) {
			t.start();
		}
		for (Thread t : ts) {
			t.join();
		}
		System.out.println(atomicInt.get()); // 1000
	}
}

二、AtomicReference

 概述:原子数组主要由AtomicIntegerArray/AtomicLongArray这些包装类
 * 主要Api方法:getAndIncrement(index),即比AtomicInteger多了一个index参数

public class ArrayAtomicDemo {
	
	private static int THREADCOUNT = 1000;
	private static CountDownLatch countDown = new CountDownLatch(THREADCOUNT);
	private static int[] values = new int[10];
	private static AtomicIntegerArray atomicValues = new AtomicIntegerArray(values);
	
	public static void main(String[] args) throws InterruptedException {
		// 1、1000个线程,每个线程循环100次,每次每个元素+1
		for (int i = 0; i < THREADCOUNT; i++) {
			new Thread(()->{
				for (int j = 0; j < 100; j++) {
					for (int k = 0; k < values.length; k++) {
						values[k]++;
					}
				}
				countDown.countDown();
			}).start();
		}
		countDown.await();
		for (int i = 0; i < 10; i++) {
			System.out.print(values[i]+" ");
		}
		//99873 99878 99872 99868 99863 99856 99868 99862 99851 99853
		System.out.println();
		
		// 2、1000个线程,每个线程循环100次,每次每个元素+1,使用AtomicIntegerArray。
		countDown = new CountDownLatch(THREADCOUNT);
		for (int i = 0; i < THREADCOUNT; i++) {
			new Thread(()->{
				for (int j = 0; j < 100; j++) {
					for (int k = 0; k < values.length; k++) {
						atomicValues.getAndIncrement(k);
					}
				}
				countDown.countDown();
			}).start();
		}
		countDown.await();
		for (int i = 0; i < 10; i++) {
			System.out.print(atomicValues.get(i)+" ");
		}
		//100000 100000 100000 100000 100000 100000 100000 100000 100000 100000
	}
	
}

三、AtomicReference

 *  AtomicReference引用原子包装类
 *  概述:AtomicInteger是对int,AtomicIntegerArray是对数组的一些CAS操作api的集合,
 *  那么AtomicReference就是包装引用类型,比如compareAndSet(expect,update)。它有一个
 *  泛型,可以指定被包装引用的类型。下面是模拟并发栈。

public class AtomicReferenceDemo<E> {
	
	AtomicReference<Node<E>> first = new AtomicReference<Node<E>>();
	
	public void push(E e){
		Node<E> newHead = new Node<E>(e);
		Node<E> oldHead;
		for (;;) {
			oldHead = first.get(); /**内部是原子变量*/
			newHead.next = oldHead;
			if(first.compareAndSet(oldHead, newHead)){ /**利用本地方法的cas操作*/
				break;
			}
		}
	}
	
	public E pop(){
		Node<E> oldHead;
		Node<E> newHead;
		do {
			oldHead = first.get();
			if (oldHead == null)
				return null;
			newHead = oldHead.next;
		} while (!first.compareAndSet(oldHead, newHead));
		return oldHead.item;
	}
	
	private static class Node<E>{
        final E item;
        Node<E> next;  /**因为都是一端进行操作,所以next不用Atomic包装!*/
        public Node(E item) {
        	this.item = item; 
        }
	}
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值