Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 从不同线程同时访问SQLite数据库_Android_Multithreading_Android Sqlite - Fatal编程技术网

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

Android 从不同线程同时访问SQLite数据库,android,multithreading,android-sqlite,Android,Multithreading,Android Sqlite,这是我的问题。我的应用程序启动几个线程,每个线程用于更新特定对象。对象的更新通过对单个数据库的查询进行。只有一个数据库和一个OpenHelper。我的应用程序的行为表明,对数据库的调用是非同步的,正如我所希望的那样。如何从不同线程同时访问同一数据库?如果每个对象的数据位于不同的表中,那么将数据库拆分为多个数据库(每个对象一个数据库)更有效吗 public class SomethingToBeUpdated implements Runnable { private SQ

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

    }

为了在各种线程中访问数据库,您需要有一个数据库管理器,它保存数据库类的一个对象,并将其传递给任何需要它的线程。在安卓系统中,您无法在多个线程中使用不同的对象同时访问数据库。它可能会阻塞您的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
使用此方法,您的数据库现在是线程安全的。希望这有帮助

如果每个对象的数据位于不同的表中,那么将数据库拆分为多个数据库(每个对象一个数据库)更有效吗

    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上使用多线程时要小心。在您的情况下,最好将
连接
与rawQuery一起使用