2015-02-12 3 views
2

Вот моя проблема. Мое приложение запускает несколько потоков, каждый для определенного объекта, который нужно обновить. Обновление объекта происходит с запросом к одной базе данных. Существует одна база данных и один OpenHelper. Поведение моего приложения подсказывает мне, что вызовы в базу данных не являются одновременно и я бы хотел. Как я могу одновременно обращаться к одной базе данных из разных потоков? Если данные для каждого объекта в разных таблицах более эффективны для разделения базы данных в нескольких базах данных, по одному для каждого объекта?Доступ к базе данных SQLite одновременно из разных потоков

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(); 
      } 
     } 

    } 
+0

Будьте осторожны с этой многопоточной резьбой на Sqlite. В вашем случае лучше использовать 'JOINS' с rawQuery –

ответ

6

Ради доступа к базе данных в различных потоках, необходимо иметь менеджер баз данных, которая хранит объект вашего класса базы данных и передать его в любой поток, который в ней нуждается. В 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 

С этим метод вашей базы данных теперь потокобезопасен. Надеюсь это поможет.

Если данные для каждого объекта находятся в разных таблицах, более эффективно разделять базу данных в нескольких базах данных, по одному для каждого объекта?

Нет, это не эффективно. У этого есть много накладных расходов, чтобы определить, получить доступ, сделать объект и запросить различные базы данных. А что, если вы хотите присоединиться к столам? вы просто не можете.

Смежные вопросы