Ява, правильно используя статические переменные, чтобы предотвратить тупик - Синхронизация

1

Я новичок в программировании на Android и не изучал Java ранее. Я действительно запутался в том, как использовать synchronized для обеспечения безопасности потоков при static variables:

Обычно я создаю класс с именем Utils который имеет некоторые static functions которые в большинстве случаев нужны всем моим другим классам. Это правильный способ сохранить повторяющийся код из моих классов.

У меня всегда возникает проблема с использованием баз данных. Когда я создаю класс sqliteHelper для определенной базы данных и пытаюсь управлять этой базой данных из службы Activity и Background, у меня обычно возникают проблемы. Если я использую локальные объекты вспомогательного класса, я максимально склонен к взаимоблокировке базы данных, когда оба вспомогательных объекта пытаются получить блокировку записи вместе.

Чтобы избавиться от этой проблемы, я создаю static экземпляр класса-помощника в моем классе utils. Теперь для выполнения любой операции с базой данных моя активность и моя служба делают следующее:

   public class Utils{
          public static MDatabaseHelper mHelper;
          public static void instantiateHelper(Context context){
          if(mHelper==null)
                mHelper=new MDatabaseHelper(context);

           }
    } 



    public class mActivity extends Activity{
     public void insert some item in database(final Item item)   // this method is called in the Activity at some time
     (new Thread(){
         @Override public void run(){
         Utils.instantiateHelper(getBaseContext());
         mHelper.insertItem(item); }
        }).start();
     }




 public class mService extends Service{
         public void insert some item in database(final Item item)    // this method is called in the service at some time
          (new Thread(){
           @Override public void run{
             Utils.instantiateHelper(getBaseContext());
             mHelper.insertItem(item); }
        }).start();
     }

Теперь, если и служба, и деятельность попытаются вставить элемент вместе. Я часто попадаю в эту ситуацию и возникает ошибка. Чтобы этого избежать, я использую этот способ:

Я помещаю операцию вставки в блок try и при отказе я жду случайного времени и повторю попытку

    public void insertSomeItemInDatabase(final Item item)
     (new Thread(){
          @Override public void run(){
              int i=0;
              Random rand=new Random();
                 while(true){
                  if(i>10)
                    return;
                  try{ 
                     Utils.instantiateHelper(getBaseContext());
                     mHelper.insertItem(item);
                     break;
                     }catch(Exception e){
                      i++;
                           try{
                              Thread.sleep(rand.nextInt(1000));
                               }catch(Exception e){}
                      }

                      }
          } 
          }
        }).start();
     }

Я знаю, что это самый худший метод синхронизации, но поскольку я настолько новичок в java может кто-нибудь объяснить, как использовать synchronized в этом сценарии.

Спасибо

  • 0
    почему ваша insertSomeItemInDatabase не синхронизируется?
  • 0
    К вашему сведению: ваш подход является распространенным методом в сетевых протоколах. Это несколько похоже на протокол Алоха . Возможно, вы захотите применить экспоненциальный откат, если вы хотите придерживаться этого подхода.
Показать ещё 4 комментария
Теги:
android-sqlite
concurrency
synchronized

1 ответ

1
Лучший ответ

Я думаю, что все, что вам нужно, - создать класс приложения

[1] Все эти переменные, которые вы использовали в Util, которые используются во всех других классах, могут быть взяты в этом классе Application. Таким образом, эти переменные будут доступны для всех других классов.

[2] Создать экземпляр Singelton класса Appliction. Просто Google об этом.

[3] Также создайте Singleton из DataBaseHelper (если это возможно и может применяться), поэтому один экземпляр помогает вам где угодно.


Класс приложения - это глобальный класс в android, поэтому вы можете использовать его для хранения и доступа ко всем глобальным данным. например:

public class AppData extends Application {

    public static AppData appData;

    public int currentUserId; // etc.

    //Const.
    public AppData() {
        appData = this;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        loginPreferences = getSharedPreferences(
            SPF_NAME, 0);

        pathToSDCard = Environment.getExternalStorageDirectory().getAbsolutePath();
        System.out.println("Path : " + pathToSDCard);
       //etc.
    }

 //    MOST IMP  FOR GETTIN SINGELTON INSTANCE     <<<---<<<---<<<---
    public static AppData getAppData() {
        return appData;
    }
}

КАК ИСПОЛЬЗОВАТЬ ЭТО, СМОТРИТЕ ЭТО

class ABC extends Activity {
    AppData appData;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.xyz);

        appData = AppData.getAppData();
        ...........
        ...........

        appData.VARIABLE_NAME...
    }
}

Еще одно. В AndroidMenifest.xml

    ...
    ...
<application             //   In Application Tag
        android:name="PACKAGE_NAME.AppData"  //  <<  Add here class name in which you have extended Application
        android:icon="@drawable/ic_launcher"
    ...
    ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню