1

我希望有人可以为我清除我的代码中发生的事情。我有一段代码读取和写入我的数据库,它既从服务运行,也从我的活动运行。无论是从服务还是活动调用,我都需要这段代码是线程安全的。因此,我采用了代码块所在的类,并制作了一个静态锁定对象以使其保持线程安全,如下面的代码块所示:

synchronized(AnalyticsMessages.sync_lock){
                Log.v("mixpanel", "locking off of: "+AnalyticsMessages.sync_lock.toString());
                String[] eventsData = mDbAdapter.generateDataString(table);
                if (eventsData != null) {
                    String lastId = eventsData[0];
                    String rawMessage = eventsData[1];
                    HttpPoster poster = getPoster(mEndpointHost, mFallbackHost);
                    HttpPoster.PostResult eventsPosted = poster.postData(rawMessage, endpointUrl);

                    if (eventsPosted == HttpPoster.PostResult.SUCCEEDED) {
                        logAboutMessageToMixpanel("Posted to " + endpointUrl);
                        logAboutMessageToMixpanel("Sent Message\n" + rawMessage);
                        //Log.v("mixpanel", "Sent Message\n" + rawMessage);
                        mDbAdapter.cleanupEvents(lastId, table);
                        Log.v("mixpanel", "removing id: "+lastId);
                    }
                    else if (eventsPosted == HttpPoster.PostResult.FAILED_RECOVERABLE) {
                        // Try again later
                        if (!hasMessages(FLUSH_QUEUE)) {
                            sendEmptyMessageDelayed(FLUSH_QUEUE, mFlushInterval);
                        }
                    }
                    else { // give up, we have an unrecoverable failure.
                        mDbAdapter.cleanupEvents(lastId, table);
                    }
                }
            }

sync_lock 在 AnalyticsMessages 中定义如下:

private static final Object sync_lock = new Object();

它显然没有正确锁定,因此带有 toString 的日志。日志告诉我,不知何故,我似乎有 2 个不同的 sync_lock 变量(因为它在内存中打印了一个地址)。我应该提到 AnalyticsMessages 是这样实例化的:

public static AnalyticsMessages getInstance(Context messageContext) {
    synchronized (sInstances) {
        Context appContext = messageContext.getApplicationContext();
        AnalyticsMessages ret;
        if (! sInstances.containsKey(appContext)) {
            if (MPConfig.DEBUG) Log.d(LOGTAG, "Constructing new AnalyticsMessages for Context " + appContext);
            ret = new AnalyticsMessages(appContext);
            sInstances.put(appContext, ret);
        }
        else {
            if (MPConfig.DEBUG) Log.d(LOGTAG, "AnalyticsMessages for Context " + appContext + " already exists- returning");
            ret = sInstances.get(appContext);
        }
        return ret;
    }
}

似乎正在发生的事情是,当服务将自己作为上下文传递给 AnalyticsMessages.getInstance 时,我最终得到了一个 sync_lock 变量,但是当我的一个活动在此处将自己作为上下文传递时,我最终得到了一个不同的变量?这是否意味着 android 服务使用与主进程不同的类加载器?有解决方法吗?我认为这实际上是一个相对普遍的问题?我完全偏离了这里发生的事情吗?提前致谢!

4

1 回答 1

2

似乎 android:process 用于我的后台服务

这是这个特定困难的常见来源。虽然从 Java 源代码的角度来看,这都是一个应用程序,但您正在运行两个单独的进程这一事实意味着您有两个单独的对象堆,因此一个堆中的全局(静态数据成员)将与同一堆不同 -在另一个堆中命名为全局。

是否有充分的理由让服务在与应用程序其他部分不同的进程中运行?

通常不会。如您所见,它会导致您的应用程序消耗更多内存和更多 CPU 时间,并限制各种组件(在不同进程中运行)的互操作能力。我通常建议不要使用多个流程。话虽如此,更改它需要进行彻底的测试,特别是如果您不知道为什么首先使用该技术。

于 2013-06-21T16:14:10.320 回答