`
san_yun
  • 浏览: 2662359 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

安全的自增类

    博客分类:
  • java
 
阅读更多

java中一个计数器如果超过MAX_VALUE再自增会如何?很可能会是负数。下面是一个安全的自增类

 

/*

 * Copyright 1999-2011 Alibaba Group.

 *  

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *  

 *      http://www.apache.org/licenses/LICENSE-2.0

 *  

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

package com.alibaba.dubbo.common.utils;



import java.util.concurrent.atomic.AtomicInteger;



/**

 * AtomicPositiveInteger

 * 

 * @author william.liangf

 * @author ding.lid

 */

public class AtomicPositiveInteger extends Number {

    

    private static final long serialVersionUID = -3038533876489105940L;

    

    private final AtomicInteger i;

    

    public AtomicPositiveInteger() {

        i = new AtomicInteger();

    }

    

    public AtomicPositiveInteger(int initialValue) {

        i = new AtomicInteger(initialValue);

    }



    public final int getAndIncrement() {

        for (;;) {

            int current = i.get();

            int next = (current >= Integer.MAX_VALUE ? 0 : current + 1);

            if (i.compareAndSet(current, next)) {

                return current;

            }

        }

    }



    public final int getAndDecrement() {

        for (;;) {

            int current = i.get();

            int next = (current <= 0 ? Integer.MAX_VALUE : current - 1);

            if (i.compareAndSet(current, next)) {

                return current;

            }

        }

    }



    public final int incrementAndGet() {

        for (;;) {

            int current = i.get();

            int next = (current >= Integer.MAX_VALUE ? 0 : current + 1);

            if (i.compareAndSet(current, next)) {

                return next;

            }

        }

    }



    public final int decrementAndGet() {

        for (;;) {

            int current = i.get();

            int next = (current <= 0 ? Integer.MAX_VALUE : current - 1);

            if (i.compareAndSet(current, next)) {

                return next;

            }

        }

    }



    public final int get() {

        return i.get();

    }



    public final void set(int newValue) {

        if (newValue < 0) {

            throw new IllegalArgumentException("new value " + newValue + " < 0");

        }

        i.set(newValue);

    }



    public final int getAndSet(int newValue) {

        if (newValue < 0) {

            throw new IllegalArgumentException("new value " + newValue + " < 0");

        }

        return i.getAndSet(newValue);

    }



    public final int getAndAdd(int delta) {

        if (delta < 0) {

            throw new IllegalArgumentException("delta " + delta + " < 0");

        }

        for (;;) {

            int current = i.get();

            int next = (current >= Integer.MAX_VALUE - delta + 1 ? delta - 1 : current + delta);

            if (i.compareAndSet(current, next)) {

                return current;

            }

        }

    }



    public final int addAndGet(int delta) {

        if (delta < 0) {

            throw new IllegalArgumentException("delta " + delta + " < 0");

        }

        for (;;) {

            int current = i.get();

            int next = (current >= Integer.MAX_VALUE - delta + 1 ? delta - 1 : current + delta);

            if (i.compareAndSet(current, next)) {

                return next;

            }

        }

    }



    public final boolean compareAndSet(int expect, int update) {

        if (update < 0) {

            throw new IllegalArgumentException("update value " + update + " < 0");

        }

        return i.compareAndSet(expect, update);

    }



    public final boolean weakCompareAndSet(int expect, int update) {

        if (update < 0) {

            throw new IllegalArgumentException("update value " + update + " < 0");

        }

        return i.weakCompareAndSet(expect, update);

    }



    public byte byteValue() {

        return i.byteValue();

    }



    public short shortValue() {

        return i.shortValue();

    }



    public int intValue() {

        return i.intValue();

    }



    public long longValue() {

        return i.longValue();

    }



    public float floatValue() {

        return i.floatValue();

    }



    public double doubleValue() {

        return i.doubleValue();

    }



    public String toString() {

        return i.toString();

    }



    @Override

    public int hashCode() {

        final int prime = 31;

        int result = 1;

        result = prime * result + ((i == null) ? 0 : i.hashCode());

        return result;

    }



    @Override

    public boolean equals(Object obj) {

        if (this == obj) return true;

        if (obj == null) return false;

        if (getClass() != obj.getClass()) return false;

        AtomicPositiveInteger other = (AtomicPositiveInteger) obj;

        if (i == null) {

            if (other.i != null) return false;

        } else if (!i.equals(other.i)) return false;

        return true;

    }



}

 

分享到:
评论

相关推荐

    java快速ID自增器

    1. **原子类**:Java的`AtomicLong`类是线程安全的,可以用于实现自增ID。每次获取新ID时,只需要调用`incrementAndGet()`方法,该方法会原子性地增加当前值并返回新的值。 2. **数据库序列**:如果使用的是支持...

    php 根据自增id创建唯一编号类

    本篇文章将详细介绍如何创建一个基于自增ID的唯一编号类,并通过算法说明和实例演示来阐述其工作原理。 首先,我们要明确目标:创建一个PHP类,它接受自增ID、自定义前缀和位数作为参数,然后生成一个唯一的编号。...

    自增运算符重载

    1. **类型安全**:确保自增运算符只对能够合理增加的类型进行操作。 2. **副作用**:前缀自增有副作用,而后缀自增有两次副作用(一次返回旧值,一次执行自增)。 3. **复合操作**:自增运算符重载要考虑与其他...

    应用级自增ID的生成

    4. **TableIdentityVo.java**:这个文件名可能表示“表身份值对象”,它是封装ID生成相关数据的类,可能包含当前ID、步长、工作节点信息等字段,并提供相应的操作方法。 在实际应用中,自增ID生成器需要考虑性能、...

    PHP基于Redis计数器类

    总结一下,通过PHP和Redis结合,我们可以构建一个可靠的计数器系统,适用于记录网站访问量、用户点击次数等需要并发安全自增的场景。Redis的原子性操作保证了数据的一致性,而PHP作为后端语言,可以方便地进行业务...

    java多线程自增效率比较及原理解析

    `AtomicInteger`是Java提供的原子整型类,它内部通过循环CAS(Compare and Swap)操作来实现线程安全的自增操作,而不需要显式地加锁解锁。 **示例代码**: ```java AtomicInteger count = new AtomicInteger(); count...

    类的方法练习

    7. Java特点:Java具有安全性、分布性和移植性,但它是一种解释和编译混合的语言,不是编译执行。选项D(编译执行)是不正确的。 8. 类的定义和使用:Java程序的基本元素是类,每个类都有一个对应的源代码文件,...

    Mongodb自增id实现方法

    通过这种方式,可以在不内置自增ID功能的情况下,确保在并发环境下安全地生成唯一的自增ID。不过,这种方法需要额外的存储空间和处理步骤,对于大规模并发写入的情况,可能需要评估性能影响。在设计数据库架构时,应...

    一个时间类

    6. **性能优化**:如果博主有涉及,可能会讨论如何优化时间类的性能,例如避免不必要的对象创建,或者利用线程安全的策略来处理并发场景下的时间操作。 7. **最佳实践**:可能还会分享一些在处理日期时间问题上的...

    Twitter的分布式自增ID雪花算法snowflake

    在Java中,实现雪花算法通常会创建一个Snowflake类,其中包含一个线程安全的序列号生成器和当前时间戳的存储。每次需要生成ID时,首先获取当前时间戳与上一次生成ID时的时间戳进行比较,如果时间戳未发生变化,则...

    MySQL表自增id溢出的故障复盘解决

    处理这类问题通常需要以下几个步骤: 1. **识别问题**:首先,需要确定表的当前最大id值,通过SQL查询`SELECT MAX(id) FROM tb1`来获取。 2. **创建影子表**:创建一个新的表tb2,其结构与tb1相同。使用`CREATE ...

    C语言中自增自减表达式的未定义行为.pdf

    C语言允许在一个表达式中使用多个赋值类运算符,包括赋值运算符、自增运算符和自减运算符等。这种灵活性让程序看起来简洁,但同时也可能引起副作用。 副作用的存在,会使程序变得难以理解,并容易产生误解或错误。...

    donkeyid, php扩展,64位自增id生成器.zip

    而`donkeyid`通过算法优化,避免了这个问题,它可以在多台服务器上安全地生成不重复的ID,支持水平扩展。 `donkeyid`的实现可能包括以下几个关键点: 1. **分布式一致性**:`donkeyid`可能采用了类似于Twitter的...

    软件安全编程常见注意事项

    1. **避免复杂参数**:在宏定义中,应避免使用自增、自减、函数调用等复杂操作,因为它们可能导致预处理器的意外行为。 2. **避免依赖计算顺序的表达式**:依赖计算顺序的表达式在不同编译器或优化级别下可能有不同...

    订单号生成工具类

    7. **工具类的设计**:在Java等编程语言中,订单号生成工具类通常会设计为线程安全,提供静态方法供调用,以确保在多线程环境下的正确性。同时,可以考虑提供配置项,允许用户自定义订单号的格式和生成策略。 8. **...

    生成以日期开头,加4位数字,每次加1的工具类.如:201712140001

    这里的`AtomicInteger`保证了在并发环境下的线程安全,`getAndIncrement()`方法会原子性地获取当前值并增加1。 其次,`FileUtil.java`可能是用来处理文件操作的辅助类,它可能包含读写文件、创建目录等方法。在本例...

    C++实验报告2

    为了允许外部代码修改和查看这些值,提供了公共的`change`和`print`方法,这就是封装,它增加了代码的安全性和可维护性。 3. 构造函数与析构函数: 在第(3)部分,`a`类的构造函数用`new`关键字动态分配了一个整型...

    Java获取最后插入MySQL记录的自增ID值的3种方法

    在Java编程中,当我们在MySQL数据库中执行插入操作并希望获取新插入记录的自增ID时,有多种方法可以实现这一需求。以下是三种常见的方法,适用于不同的场景。 **方法一:使用PreparedStatement的RETURN_GENERATED_...

    MySQL字段自增自减的SQL语句示例介绍

    总结来说,MySQL提供了灵活的表达式和函数来处理字段的自增自减操作,使得我们可以安全地更新计数器类字段,而不用担心数值溢出的问题。在编写这类SQL语句时,一定要考虑到字段的数据类型和可能的边界情况,以确保...

    mybatis-plus实体类主键策略有3种(小结)

    注解方式适用于单个实体类,全局配置适用于项目中大部分实体类的共性需求,而默认策略则是一个安全的后盾,保证了在未明确指定策略时的正常运行。理解并正确运用这些策略,可以优化数据库操作,提高系统的稳定性和可...

Global site tag (gtag.js) - Google Analytics