我有一个小型数据收集应用程序,它只有一个按钮来启动和停止服务。
该服务又开始一个新线程。每当有关于电压变化的广播时,它都会收集有关电压变化的数据。
数据暂时存储在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);
}
答案 0 :(得分:1)
从堆栈跟踪中可以看出,当您从多个线程访问java.util.ConcurrentModificationException
时,错误似乎是ArrayList
。您可以查看How to Avoid ConcurrentModificationException when using an Iterator,相关部分如下:
在多线程环境中避免ConcurrentModificationException:
您可以将列表转换为数组,然后迭代数组。这种方法适用于中小型列表,但如果列表很大,则会对性能产生很大影响。
您可以通过将列表放在同步块中来锁定列表。不建议采用这种方法,因为它会停止多线程的好处。
- 醇>
如果您使用的是JDK1.5或更高版本,则可以使用ConcurrentHashMap和CopyOnWriteArrayList类。这是推荐的方法。
1&GT;我每隔10秒打开和关闭数据库。我应该只在整个应用程序完成时将设计更改为关闭数据库。
每隔10秒打开和关闭数据库的开销就不那么大了。只有在遇到性能问题时才能想到这一点。
2&GT;我也带了一个唤醒锁,但这并没有任何区别。我也应该把唤醒锁用于我的服务吗?
似乎与特定问题无关。
3&GT;最后我怎么才能知道错误,因为我的应用已经停止了(我无法连接到USB以便知道因为我希望电池处于耗尽模式
希望你已经明白如何做到这一点。重申一下,即使应用程序停止后,您也可以通过DDMS或使用adb命令获取logcat输出:adb logcat -d > log.txt