【问题标题】:java ,Properly using Static variables to prevent deadlock - Synchronizingjava,正确使用静态变量防止死锁 - 同步
【发布时间】:2012-10-05 10:14:40
【问题描述】:

我是 android 编程新手,之前没有深入研究过 java。我真的很困惑如何使用synchronized 来确保static variables 上的线程安全:

我通常创建一个名为Utils 的类,其中包含一些static functions,这是我所有其他类大部分时间都需要的。这是将重复代码排除在我的课程之外的正确方法吗?

我总是遇到使用数据库的问题。当我为某个数据库创建 sqliteHelper 类并尝试从 Activity 和后台服务管理该数据库时,我通常会得到 陷入麻烦。如果我使用辅助类的本地对象,当两个辅助对象尝试一起获取写锁时,我最容易陷入数据库死锁。

为了摆脱这个麻烦,我在我的utils 类中创建了一个帮助类的static 实例。现在,为了对数据库执行任何操作,我的活动和服务执行以下操作:

   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

谢谢

【问题讨论】:

  • 为什么您的 insertSomeItemInDatabase 没有同步?
  • 仅供参考:您的方法是网络协议中的常用方法。它有点类似于Aloha Protocol。如果你想坚持这种方法,你可能想申请exponantial back off
  • 我对同步静态变量了解不多。一个代码 sn-p 和解释将是一个很大的帮助@njzk2
  • 当两个帮助对象尝试一起获取写锁时,“进入数据库死锁”是什么意思。如果你只有一把锁,就没有机会出现死锁情况,你需要不止一把锁。
  • 没有什么是静态的。只需将 synchronized 放在您的 insertItem 方法的声明中。这意味着一次只有一个线程可以访问它,其他线程正在排队等待。

标签: java android concurrency synchronized android-sqlite


【解决方案1】:

我认为您只需要创建应用程序类

[1] 你在 Util 中获取的所有变量,几乎在所有其他类中都会用到,都可以在这个 Application 类中获取。所以这些变量将可用于所有其他类。

[2]创建应用程序类的Singelton实例。只需谷歌即可。

[3] 还要创建DataBaseHelper的Singleton(如果可能并且可以应用),所以,单实例可以帮助你到任何地方。


Application Class 是 android 中的 Global 类,因此您可以使用它来存储和访问所有 Global-Data。例如:

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"
    ...
    ...

【讨论】:

    猜你喜欢
    • 2016-04-01
    • 2019-08-14
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多