java中的原子操作类AtomicInteger及其实现原理
来源:互联网 发布:数据分析平台需求文档 编辑:程序博客网 时间:2024/06/05 10:36
/**
* 一,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:原子更新整形的字段的更新器
五,java原子操作类在实际项目中的应用(java原子操作类的应用场景)
* 一,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) {// 初始值为1AtomicInteger 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的初始值为1000User user = new User();user.setUserName("yangcq");user.setAge(1000);// 原子更新引用数据类型的字段值System.out.println(atomicIntegerFieldUpdater.getAndIncrement(user));// 更新以后的值System.out.println(atomicIntegerFieldUpdater.get(user));}//实体类Userpublic 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中获取计数器countif (null == count) {count = new AtomicInteger(1); // 如果计数器为空,则初始化值为1context.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;}}
0 0
- java中的原子操作类AtomicInteger及其实现原理
- java中的原子操作类AtomicInteger及其实现原理
- Java 原子操作类详解(AtomicInteger、AtomicIntegerArray等)
- java原子操作实现原理
- volatile AtomicInteger java多线程操作 原子性
- Java原子操作AtomicInteger的用法
- 原子性操作类AtomicInteger等
- 原子操作 AtomicInteger
- java 原子变量AtomicInteger
- Java实现原子操作的原理
- Java 并发 ---原子操作的实现原理
- java中的原子操作类
- Java中的原子操作类
- JAVA中的原子操作类
- java.util.concurrent.atomic 并发包下的原子操作类(AtomicBoolean,AtomicInteger,AtomicLong......))
- java中的原子操作
- Java中的原子操作
- java 线程原子问题 AtomicInteger
- map使用方法更新
- C++类中的static数据成员,static成员函数
- MySql之分页优化
- java内存模型:volatile变量、与synchronized
- 【译】你想知道的关于JavaScript作用域的一切
- java中的原子操作类AtomicInteger及其实现原理
- ubuntu 16.04 vim文本编辑器的使用方法
- (6) Google2012笔试卷
- 进程间通信:消息队列(代码实现)
- python并行(1)
- setTimeout延时0毫秒的作用
- LIBSVM学习(六)代码结构及c-SVC过程
- 深入讲解SpringMVC配置文件
- 数据预处理之独热编码