【问题标题】:Access SQLite database simultaneously from different threads从不同线程同时访问 SQLite 数据库
【发布时间】:2015-02-13 06:58:16
【问题描述】:

这是我的问题。我的应用程序启动了几个线程,每个线程都针对要更新的特定对象。对象的更新发生在对单个数据库的查询中。有一个数据库和一个 OpenHelper。我的应用程序的行为表明对数据库的调用不是同时进行的,正如我所愿。如何同时从不同线程访问同一个数据库?如果每个对象的数据在不同的表中,将数据库拆分为多个数据库,每个对象一个数据库更有效?

    public class SomethingToBeUpdated implements Runnable {

       private SQLiteDatabase db;

       @Override 
       public void run() {
         db.rawQuery( ... bla bla
       }

    }

    public class MainActivity extends Activity {

       private SomethingToBeUpdated[] list = bla bla...

       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          for( SomethingToBeUpdated x : list ) {
             new Thread(x).start();
          }
       }

    }

【问题讨论】:

  • 小心 Sqlite 上的这种多线程。在您的情况下,最好将 JOINS 与 rawQuery 一起使用

标签: android multithreading android-sqlite


【解决方案1】:

为了在各种线程中访问数据库,您需要有一个数据库管理器来保存您的数据库类的对象并将其传递给需要它的任何线程。在 android 中,您不能在具有不同对象的多个线程中同时访问数据库。它可能会阻塞你的 UI(我几天前遇到的问题)。

所以要克服这个问题,你可以使用我使用的数据库管理器,它的定义如下:

public class DatabaseManager {
    private AtomicInteger mOpenCounter = new AtomicInteger();

    private static DatabaseManager instance;
    private static SQLiteOpenHelper mDatabaseHelper;
    private SQLiteDatabase mDatabase;

    public static synchronized void initializeInstance(SQLiteOpenHelper helper) {
        if (instance == null) {
            instance = new DatabaseManager();
            mDatabaseHelper = helper;
        }
    }

    public static synchronized DatabaseManager getInstance() {
        if (instance == null) {
            throw new IllegalStateException(DatabaseManager.class.getSimpleName() +
                    " is not initialized, call initializeInstance(..) method first.");
        }

        return instance;
    }

    public synchronized SQLiteDatabase openDatabase() {
        if(mOpenCounter.incrementAndGet() == 1) {
            mDatabase = mDatabaseHelper.getWritableDatabase();
        }
        return mDatabase;
    }

    public synchronized void closeDatabase() {
        if(mOpenCounter.decrementAndGet() == 0) {
            mDatabase.close();
        }
    }
}

然后你像这样初始化一次:

DatabaseManager.initializeInstance(new ChatSQL(c));

然后你就可以用这个语法在任何你想要的地方获取数据库对象:

SQLiteDatabase db = DatabaseManager.getInstance().openDatabase(); //in your methods which are querying the database

使用这种方法,您的数据库现在是线程安全的。希望这会有所帮助。

如果每个对象的数据在不同的表中,将数据库拆分为多个数据库,每个对象一个数据库更有效?

不,它没有效率。定义、访问、创建对象和查询不同的数据库有很多开销。如果你想加入表格怎么办?你就是不能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多