android - 从不同线程同时访问 SQLite 数据库

标签 android multithreading android-sqlite

这是我的问题。我的应用程序启动多个线程,每个线程用于要更新的​​特定对象。对象的更新通过对单个数据库的查询进行。有一个数据库和一个 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();
          }
       }

    }

最佳答案

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

因此,为了解决这个问题,您可以使用我使用的数据库管理器,其定义如下:

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

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

If the data for each object are in different tables is more efficient to split the database in several databases, one for each object?

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

关于android - 从不同线程同时访问 SQLite 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28489238/

相关文章:

android - 如果我的 Sqlite 数据库更新,则更新当前 Activity

java - Android SQLite 更新行不起作用

android - 在 SurfaceView 上刷新 View 时出错

android - 如何创建顶行带有矩形按钮的布局?

java - JSON 读取内部数组

c++ - 使用 _beginthreadex、__stdcall 和 lambda 创建线程

c# - 如果不使用锁定,这不应该失败吗?简单生产者消费者

android - Android 中的自定义主题

c++ - 如何使用新的 C++17 执行策略?

android - 我无法将 textview 字符串存储到 Android 中的 Sqlite 数据库中。下面是我的DatabaseHelper代码