java中的原子操作类AtomicInteger及其实现原理

        /**
         * 一,AtomicInteger 是如何实现原子操作的呢?
         *
         * 我们先来看一下getAndIncrement的源代码:
         *    public final int getAndIncrement() {
         *        for (;;) {
         *              int current = get();  // 取得AtomicInteger里存储的数值
         *            int next = current + 1;  // 加1
         *            if (compareAndSet(current, next))   // 调用compareAndSet执行原子更新操作
         *                return current;
         *        }
         *    }
         *
         * 这段代码写的很巧妙:
         * 1,compareAndSet方法首先判断当前值是否等于current;
         * 2,如果当前值 = current ,说明AtomicInteger的值没有被其他线程修改;
         * 3,如果当前值 != current,说明AtomicInteger的值被其他线程修改了,这时会再次进入循环重新比较;
         *    
         * 注意这里的compareAndSet方法,源代码如下:
         * public final boolean compareAndSet(int expect, int update) {
         *     return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
         * }
         *
         * 调用Unsafe来实现
         * private static final Unsafe unsafe = Unsafe.getUnsafe();
         *
         * 二,java提供的原子操作可以原子更新的基本类型有以下三个:
         *
         * 1,AtomicBoolean
         * 2,AtomicInteger
         * 3,AtomicLong
         *
         * 三,java提供的原子操作,还可以原子更新以下类型的值:
         *
         * 1,原子更新数组,Atomic包提供了以下几个类:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
         * 2,原子更新引用类型,也就是更新实体类的值,比如AtomicReference<User>
         * AtomicReference:原子更新引用类型的值
         * AtomicReferenceFieldUpdater:原子更新引用类型里的字段
         * AtomicMarkableReference:原子更新带有标记位的引用类型
         * 3,原子更新字段值
         * AtomicIntegerFieldUpdater:原子更新整形的字段的更新器
         * AtomicLongFieldUpdater:原子更新长整形的字段的更新器
         * AtomicStampedReference:原子更新带有版本号的引用类型的更新器
         *
         *

         */


示例代码如下:

import java.util.concurrent.atomic.AtomicInteger;
import sun.misc.Unsafe;

public class TestAtomic {

	/**
	 * @param java中的原子操作类AtomicInteger
	 * @author yangcq
	 * 
	 * 关于AtomicInteger的说明(来自官方文档注解)
	 * /**
	 * An {@code int} value that may be updated atomically.  See the
	 * {@link java.util.concurrent.atomic} package specification for
	 * description of the properties of atomic variables. An
	 * {@code AtomicInteger} is used in applications such as atomically
	 * incremented counters, and cannot be used as a replacement for an
	 * {@link java.lang.Integer}. However, this class does extend
	 * {@code Number} to allow uniform access by tools and utilities that
	 * deal with numerically-based classes.
	 *
	 * @since 1.5
	 * @author Doug Lea
	 */
	public static void main(String[] args) {
		// 初始值为1
		AtomicInteger atomicInteger = new AtomicInteger(1);
		System.out.println("--初始值atomicInteger = " + atomicInteger);
		
		// 以原子方式将当前值加1,注意这里返回的是自增前的值 
		System.out.println("atomicInteger.getAndIncrement() = " + atomicInteger.getAndIncrement());
		System.out.println("--自增后的 atomicInteger = " + atomicInteger);
		
		// 以原子方式将当前值减1,注意这里返回的是自减前的值 
		System.out.println("atomicInteger.getAndIncrement() = " + atomicInteger.decrementAndGet());
		System.out.println("--自减后的 atomicInteger = " + atomicInteger);
		
		// 以原子方式将当前值与括号中的值相加,并返回结果
		System.out.println("atomicInteger.getAndIncrement() = " + atomicInteger.addAndGet(10));
		System.out.println("--自减后的 atomicInteger = " + atomicInteger);
		
		// 如果输入的值等于预期的值,则以原子方式将该值设置成括号中的值
		System.out.println("atomicInteger.getAndIncrement() = " + atomicInteger.compareAndSet(1, 2));
		System.out.println("--自减后的 atomicInteger = " + atomicInteger);
		System.out.println("atomicInteger.getAndIncrement() = " + atomicInteger.compareAndSet(11, 9999));
		System.out.println("--自减后的 atomicInteger = " + atomicInteger);
		
		/**
		 * 一,AtomicInteger 是如何实现原子操作的呢?
		 * 
		 * 我们先来看一下getAndIncrement的源代码:
		 *    public final int getAndIncrement() {
		 *        for (;;) {
		 *	          int current = get();  // 取得AtomicInteger里存储的数值
		 *            int next = current + 1;  // 加1
		 *            if (compareAndSet(current, next))   // 调用compareAndSet执行原子更新操作
		 *                return current;
		 *        }
		 *    }
		 * 
		 * 这段代码写的很巧妙:
		 * 1,compareAndSet方法首先判断当前值是否等于current;
		 * 2,如果当前值 = current ,说明AtomicInteger的值没有被其他线程修改;
		 * 3,如果当前值 != current,说明AtomicInteger的值被其他线程修改了,这时会再次进入循环重新比较;
		 *    
		 * 注意这里的compareAndSet方法,源代码如下:
		 * public final boolean compareAndSet(int expect, int update) {
		 *     return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 
		 * }
		 * 
		 * 调用Unsafe来实现
		 * private static final Unsafe unsafe = Unsafe.getUnsafe();
		 * 
		 * 二,java提供的原子操作可以原子更新的基本类型有以下三个:
		 * 
		 * 1,AtomicBoolean
		 * 2,AtomicInteger
		 * 3,AtomicLong
		 * 
		 * 三,java提供的原子操作,还可以原子更新以下类型的值:
		 * 
		 * 1,原子更新数组,Atomic包提供了以下几个类:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
		 * 2,原子更新引用类型,也就是更新实体类的值,比如AtomicReference<User>
		 * AtomicReference:原子更新引用类型的值
		 * AtomicReferenceFieldUpdater:原子更新引用类型里的字段
		 * AtomicMarkableReference:原子更新带有标记位的引用类型
		 * 3,原子更新字段值
		 * AtomicIntegerFieldUpdater:原子更新整形的字段的更新器
		 * AtomicLongFieldUpdater:原子更新长整形的字段的更新器
		 * AtomicStampedReference:原子更新带有版本号的引用类型的更新器
		 * 
		 * 
		 */
	}

}

四,AtomicIntegerFieldUpdater:原子更新整形的字段的更新器

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

public class TestAtomicIntegerFieldUpdater {

	/**
	 * @param AtomicIntegerFieldUpdater:原子更新整形的字段的更新器
	 * @author yangcq
	 */
	
	// 创建原子更新器,并设置需要更新的对象类和对象的属性
	private static AtomicIntegerFieldUpdater<User> atomicIntegerFieldUpdater 
		= AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
	
	public static void main(String[] args) {
		
		// 设置age的初始值为1000
		User user = new User();
		user.setUserName("yangcq");
		user.setAge(1000);
		
		// 原子更新引用数据类型的字段值
		System.out.println(atomicIntegerFieldUpdater.getAndIncrement(user));
		// 更新以后的值
		System.out.println(atomicIntegerFieldUpdater.get(user));
	}
	
	//实体类User
	public static class User{
		private String userName;
		public volatile int age;

		// setter、getter方法
		public String getUserName() {
			return userName;
		}
		public void setUserName(String userName) {
			this.userName = userName;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
	}

}

五,java原子操作类在实际项目中的应用(java原子操作类的应用场景)

java原子操作类 AtomicInteger 在实际项目中的应用。HttpClientFacotryBean工厂会工作在多线程环境中,生成Httpclient,
就相当于建立HttpClient连接,通过工厂模式控制HttpClient连接,能够更好的管理HttpClient的生命周期。而我们使用java原子
操作类AtomicInteger来控制计数器,就是为了保证,在多线程的环境下,建立HttpClient连接不会出错,不会出现2个线程竞争一个
HttpClient连接的情况。


bean配置如下:
    <bean id="Httpclient" name="httpclient" class="com.yangcq.initBean.HttpClientFacotryBean">
        <property name="connectionManager" ref="connectionManagers" ></property>
        <property name="map">
            <map>
                <entry key="http.socket.timeout" value="30000" />
                <entry key="http.connection.timeout" value="30000" />
                <entry key="http.conn-manager.timeout"  value="6000" />
            </map>
        </property>
    </bean>

java实现类:
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerPNames;
import org.apache.http.conn.params.ConnManagerParamBean;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpConnectionParamBean;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
 * 在容器启动时注入connectionManager,然后初始化httpClient
 * 主要参数:
 * CONNECTION_TIMEOUT : 连接主机超时时间设置
 * SO_TIMEOUT :         读取主机数据超时时间设置
 * TIMEOUT :            获取连接超时时间
 */
public class HttpClientFacotryBean implements FactoryBean,InitializingBean,DisposableBean {
	private static final Logger logger = Logger.getLogger(HttpClientFacotryBean.class);
	private DefaultHttpClient httpClient;
	private ClientConnectionManager clientConnectionManager = null;
	private Map map = null;	
	//设置httpClient超时参数
	public void afterPropertiesSet() throws Exception {
		if (null == clientConnectionManager) {
			throw new BeanInitializationException("The connection manager must be set in " + this.getClass().getName() + "...");
		}
		HttpParams httpParams = new BasicHttpParams();
		if (null != map) {
			HttpConnectionParamBean httpConnectionParamBean = new HttpConnectionParamBean(httpParams);
			String connectionTimeout = (String) map.get(CoreConnectionPNames.CONNECTION_TIMEOUT);
			if (null != connectionTimeout)
				httpConnectionParamBean.setConnectionTimeout(Integer.parseInt(connectionTimeout));
			String soTimeout = (String) map.get(CoreConnectionPNames.SO_TIMEOUT);
			if (null != connectionTimeout)
				httpConnectionParamBean.setSoTimeout(Integer.parseInt(soTimeout));
			ConnManagerParamBean connManagerParamBean = new ConnManagerParamBean(httpParams);
			String timeout = (String) map.get(ConnManagerPNames.TIMEOUT);
			if (null != timeout)
				connManagerParamBean.setTimeout(Long.parseLong(timeout));
		}
		this.httpClient = new DefaultHttpClient(clientConnectionManager, httpParams);
		this.httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
			public void process(final HttpRequest request,final HttpContext context) throws HttpException,IOException {
				AtomicInteger count = (AtomicInteger) context.getAttribute("count"); // 从HttpContext中获取计数器count
				if (null == count) {
					count = new AtomicInteger(1); // 如果计数器为空,则初始化值为1
					context.setAttribute("count", count); // 放到context中
				}
				request.addHeader("Count", Integer.toString(count.getAndIncrement())); // 把计数器放到request请求中
				if (logger.isDebugEnabled()) {
					logger.debug("\n=====这是第 " + count + " 次连接=====\n");
				}
			}
		});
	}
	public void destroy() throws Exception {
		if (null != params)
			map.clear();
		if (null != clientConnectionManager)
			clientConnectionManager.closeExpiredConnections();
	}
	public ClientConnectionManager getConnectionManager() {
		return clientConnectionManager;
	}
	public Map getParams() {
		return map;
	}
	public void setConnectionManager(ClientConnectionManager clientConnectionManager) {
		this.clientConnectionManager = clientConnectionManager;
	}
	public void setParams(Map map) {
		this.map = map;
	}
	public Object getObject() throws Exception {
		return this.httpClient;
	}	
	public Class getObjectType() {
		return HttpClient.class;
	}
	public boolean isSingleton() {
		return false;
	}
}



  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值