【JavaEE+Android】AtomicInteger解决对

作者: 吾非言 | 来源:发表于2017-10-11 22:31 被阅读237次

    作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc

    本文选自书客创作平台第26篇文章。阅读原文

    书客创作

    AtomicInteger很多开发者,对它还是很陌生的,那么AtomicInteger是什么呢?可用来干什么呢?

    一、AtomicInteger简介

    AtomicInteger出自jdk5.0,它继承Number,实现对整形数据的处理。

    class AtomicInteger extends Number implements java.io.Serializable
    /**
     * An {@codeint} value that may be updated atomically.  See the
     * {@linkjava.util.concurrent.atomic} package specification for
     * description of the properties of atomic variables. An
     * {@codeAtomicInteger} is used in applications such as atomically
     * incremented counters, and cannot be used as a replacement for an
     * {@linkjava.lang.Integer}. However, this class does extend
     * {@codeNumber} to allow uniform access by tools and utilities that
     * deal with numerically-based classes.
     *
     *@since1.5
     *@authorDoug Lea
     */
    

    二、AtomicInteger理解

    为什么官方会提供这么一个类,来处理整形数据呢?对整形的处理,本身并不是很难,但是在一些特殊的环境下,对整形的处理可能不仅仅是简单的处理就能规避一个错误的发生。

    例如:程序中有一个变量i,通过线程执行i++操作,线程执行完后跳转到主线程进行操作,这是编程过程中经常使用的一种情况,但是如果是在一组线程都对变量i进行操作,那么该组各个线程都将会对i进行操作,这样最终跳转到主线程中变量i的值可能会不确定。原因是当i要在主线程中执行时候,可能某个子线程刚好要修改i的值,这样就会出现i的值混乱,这时候我们可能需要使用synchronized(同步)关键字进行处理。

    那么AtomicInteger为什么可以解决多线程安全问题呢?

    查看Java源码可以知道,AtomicInteger实际上是借助sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe()来实现对整形数据的操作。Unsafe类可以用来在任意内存地址位置处读写数据。可以简单的理解AtomicInteger可以对内存进行读写操作,所以无论是从效率上,还是从安全性上AtomicInteger都会更胜一筹。

    三、AtomicInteger常用API

    // 获取当前的值
    public final int get();
    // 取当前的值,并设置新的值
    public final int getAndSet(int newValue);
    // 获取当前的值,并自增
    public final int getAndIncrement();
    // 获取当前的值,并自减
    public final int getAndDecrement();
    // 获取当前的值,并加上预期的值
    public final int getAndAdd(int delta);
    

    四、AtomicInteger使用场景

    除了上面举例所说多线程对整形变量处理操作可以应用到。其实AtomicInteger还可以用于很多地方,例如利用AtomicInteger规避数据库锁的问题。

    例如:在进行数据库(SQLite)操作的时候,每一次对数据库读写都会进行一次数据库的打开和关闭的过程,如果频繁的对数据库进行读写,可能会出现一种情况,就是当对数据库读写的时候,数据库已经关闭了,这个时候就会报出数据库锁的错误,如何解决这一问题?可以通过AtomicInteger。

    SQLiteOpenHelper为android.database.sqlite包下一个专门操作SQLite的帮助抽象类。

    class SQLiteHelper extends SQLiteOpenHelper {
       private AtomicIntegerm OpenCounter=new AtomicInteger(0);
       private SQLiteDatabase mDatabase;
       private static SQLiteHelper SQLiteHelper;
    
       /**
        *获取MySqliteHelper,单列模式
        *
        *@paramcontext上下文对象
        *@return
        */
       static synchronized SQLiteHelper getSqliteHelper(Context context) {
          if(SQLiteHelper==null)
             SQLiteHelper=new SQLiteHelper(context);
          return SQLiteHelper;
       }
    
       /**
        *打开数据库
        */
       synchronized SQLiteDatabase openDatabase() {
          if(mOpenCounter.incrementAndGet() ==1) {
             mDatabase=SQLiteHelper.getWritableDatabase();
          }
          return mDatabase;
       }
    
       /**
        *关闭数据库
        */
       synchronized void closeDatabase() {
          if(mOpenCounter.decrementAndGet() ==0) {
             mDatabase.close();
          }
       }
    
       /**
        *构造函数
        *
        *@paramcontext上下文对象
        *@paramname创建数据库的名称
        *@paramfactory游标工厂
        *@paramversion创建数据库版本>= 1
        */
       public SQLiteHelper(Context context,String name,SQLiteDatabase.CursorFactory factory, intversion) {
          super(context,name,factory,version);
       }
       private SQLiteHelper(Context context) {
          // 创建数据库
          super(context,SQLiteConstant.DB_NAME, null,SQLiteConstant.DB_VERSION);
       }
    
       /**
        *当数据库创建时回调的函数
        *
        *@paramdb数据库对象
        */
       @Override
       public void onCreate(SQLiteDatabase db) {
          //创建数据表
          db.execSQL(SQLiteConstant.SQL_CREATE_TABLE_USER);
       }
    
       /**
        *当数据库版本更新的时候回调函数
        *
        *@paramdb数据库对象
        *@paramoldVersion数据库旧版本
        *@paramnewVersion数据库新版本
        */
       @Override
       public voidonUpgrade(SQLiteDatabase db, intoldVersion, intnewVersion) {
          //升级数据库
          db.execSQL(SQLiteConstant.SQL_DROP_TABLE_USER);
          db.execSQL(SQLiteConstant.SQL_CREATE_TABLE_USER);
       }
    }
    

    阅读原文


    微信公众号:书客创作

    相关文章

      网友评论

        本文标题:【JavaEE+Android】AtomicInteger解决对

        本文链接:https://www.haomeiwen.com/subject/orcqextx.html