1

我有一个小型数据收集应用程序,它有一个按钮来启动和停止服务。

该服务反过来启动一个新线程。每当有关于它的广播时,它都会收集有关电压变化的数据。

数据临时存储在 ArrayList 中,每隔 10 秒将存储在 arrayList 中的所有数据转储到数据库中。

应用程序运行良好 10-20 分钟,但 20 分钟后应用程序自动停止。有时服务仍在运行,有时服务也被杀死。

你们能告诉我这里可能是什么问题吗?我认为可能与这个问题有关的事情是:

1.> 我每 10 秒打开和关闭一次数据库。只有在整个应用程序完成后,我才应该将设计更改为关闭数据库。

2.> 我也使用了唤醒锁,但这并没有什么不同。我也应该为我的服务使用唤醒锁吗?

3.> 最后,我如何才能知道导致我的应用程序停止的错误(我无法连接到 USB 以知道因为我希望电池处于耗尽模式)

更新

logcat报错如下:

E/AndroidRuntime( 9770): FATAL EXCEPTION: Timer-0
E/AndroidRuntime( 9770): java.util.ConcurrentModificationException
E/AndroidRuntime( 9770):    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
E/AndroidRuntime( 9770):    at com.amazon.hsyal.services.LoggerThread$2.run(LoggerThread.java:78)
E/AndroidRuntime( 9770):    at java.util.Timer$TimerImpl.run(Timer.java:284)
W/ActivityManager(  236):   Force finishing activity com.amazon.hsyal/.ui.VoltageSODLoggerActivity
I/ActivityManager(  236): No longer want com.amazon.dcp:OTAService (pid 12299): hidden #16
I/WindowManager(  236): WIN DEATH: Window{417dcd20 com.amazon.hsyal/com.amazon.hsyal.ui.VoltageSODLoggerActivity paused=true}
I/UsageStats(  236): No package stats for pkg:com.amazon.kindle.otter
I/ActivityManager(  236): Process com.amazon.hsyal (pid 9770) has died.
W/ActivityManager(  236): Scheduling restart of crashed service com.amazon.hsyal/.services.LoggerService in 5000ms
I/ActivityManager(  236): Start proc com.amazon.kindle for broadcast com.amazon.kindle/.PrimeAppReceiver: pid=13075 uid=32022 gids={3003, 1015}
W/ActivityManager(  236): Activity pause timeout for ActivityRecord{4173eb10 com.amazon.kindle.otter/.Launcher}
I/ActivityManager(  236): Start proc com.android.settings for broadcast com.android.settings/.TopWindowChangereceiver: pid=13111 uid=1000 gids={1015, 3002, 3001, 3003}
I/ActivityManager(  236): Start proc com.amazon.hsyal for service com.amazon.hsyal/.services.LoggerService: pid=13138 uid=10051 gids={}
W/ActivityManager(  236): Activity destroy timeout for ActivityRecord{41750838 com.amazon.hsyal/.ui.VoltageSODLoggerActivity}

对应的Thread代码如下:

public void run() {
    // TODO Auto-generated method stub
    dbInstance = new DbClass(ctx);
    Log.d("Debuglogger","Came inside thread");
    ctx.registerReceiver(this.voltageReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            if(threadStatus == false){
                return;
            }
            if(!DataClass.dataList.isEmpty()){
                dbInstance.open();
                Iterator<DataClass> itr = DataClass.dataList.iterator();
                DataClass a_temp;
                while(itr.hasNext()){
                    a_temp = itr.next();
                    dbInstance.createEntry(a_temp.getVoltage(), a_temp.getCurrent(), a_temp.getBattery_level(),
                            a_temp.getTime(), a_temp.getRtime());
                }
                dbInstance.close();
                DataClass.dataList.clear();
                Log.d("db-error", "Data written to database and list cleared !");
            }
        }}, 0, UPDATE_INTERVAL);
}
4

1 回答 1

1

正如您从堆栈跟踪中看到的那样,错误似乎是java.util.ConcurrentModificationException当您ArrayList从多个线程访问时。你可以看看How to Avoid ConcurrentModificationException when using an Iterator,其相关部分如下:

在多线程环境中避免 ConcurrentModificationException:

  1. 您可以将列表转换为数组,然后对数组进行迭代。这种方法适用于中小型列表,但如果列表很大,则会对性能产生很大影响。

  2. 您可以在迭代时锁定列表,方法是将其放入同步块中。不推荐这种方法,因为它会失去多线程的好处。

  3. 如果您使用的是 JDK1.5 或更高版本,则可以使用 ConcurrentHashMap 和 CopyOnWriteArrayList 类。这是推荐的方法。


1.> 我每 10 秒打开和关闭一次数据库。只有在整个应用程序完成后,我才应该将设计更改为关闭数据库。

每 10 秒打开和关闭一次数据库的开销并不大。仅当您遇到性能问题时才考虑这一点。

2.> 我也使用了唤醒锁,但这并没有什么不同。我也应该为我的服务使用唤醒锁吗?

似乎与特定问题无关。

3.> 最后,我如何才能知道导致我的应用程序停止的错误(我无法连接到 USB 以知道因为我希望电池处于耗尽模式

希望您已经了解如何做到这一点。重申一下,即使在应用程序停止后,您也可以获得 logcat 输出 - 通过 DDMS 或使用 adb 命令:adb logcat -d > log.txt

于 2012-07-02T06:29:36.790 回答