服务,线程,活动和静态ArrayList

时间:2012-08-29 10:53:44

标签: java android multithreading

我有一个非粘性服务,通过广播接收器定期调用,以启动一个执行某些任务的线程。当线程正在运行时,持续通知会显示一些进度信息,以及一个用于显示状态页面的按钮。

此状态页面显示了正在处理的项目列表,此列表是线程和此活动使用的静态ArrayList。当状态活动开始时,我有一个空检查:

if(Global.statusItems == null)
{
    Global.statusItems = new ArrayList<StatusPageItem>();
}

线程仍然在运行,并且可以完全访问ArrayList,但是一旦启动了Status Activity,它就会重新创建ArrayList,就好像它是null一样。

到目前为止,我还没有能够在没有使用ObjectOutputStream保存列表的情况下解决问题,并在状态页面启动时重新加载。我可以使用更优雅的解决方案吗?

此致 五重峰

2 个答案:

答案 0 :(得分:1)

您需要确保2行代码(空测试和创建新列表)是原子的,并且分配在其他线程中是可见的。

最简单的方法是同步这段代码:

synchronized(Global.class) {
    if(Global.statusItems == null) {
        Global.statusItems = new ArrayList<StatusPageItem>();
    }
}

但是,如果您需要从一个线程读取列表并从另一个线程写入该列表,则需要在添加/删除/迭代时添加额外的同步,以确保两个步骤都看到相同的列表 - 如果您没有但是,写作线程可能会将一个项目添加到列表中,但是阅读线程看不到它。

最简单的方法是使用list的线程安全实现:

synchronized(Global.class) {
    if(Global.statusItems == null) {
        Global.statusItems = new CopyOnWriteArrayList<StatusPageItem>();
    }
}

如果关注内存/对象(从这个角度来看CopyOnWriteArrayList效率不高),你也可以使用同步集合:

synchronized(Global.class) {
    if(Global.statusItems == null) {
        Global.statusItems = Collections.synchronizedList(new ArrayList<StatusPageItem>());
    }
}

在这种情况下,请确保在迭代时锁定集合:

synchronized(Global.statusItems) {
    for (StatusPageItem item : Global.statusItems) {

    }
}

答案 1 :(得分:1)

您的服务是否可能在其他process上运行?