4

我有一个函数:填充从 SQLite DB调用fillFromDB的实例。ArrayListlist

我还有另一个Thread应该清除它list并重新填充它。

我在列表中遇到了一些问题,因为有时另一个会Thread清除列表,而第一个仍在填充它,从而导致IndexOutOfBoundsException适配器。

// This occurs onCreate()
fillFromDb(list);
downloadAndRepopulateList(list);


private void downloadAndRepopulateList(List list) {
    new Thread(new Runnable() {
        @Override public void run() {
            list.clear();
            // Some other clode
        }
    }
}

我知道问题是因为它们不是线程安全的,但我以前从未使用synchronized过。

所以我的问题是:

如果我像这样更改下载功能:

private void downloadAndRepopulateList(List list) {
    new Thread(new Runnable() {
        @Override public void run() {

            synchronized(list) {

                list.clear();
                // Some other clode
            }
        }
    }
}

它会等待 UIThread 完成填充列表fillFromDb()然后继续清除并重新填充它吗?

如果没有,我该怎么做?

4

2 回答 2

5

虽然我宁愿推荐使用LinkedBlockingQueue. IE

  list = new LinkedBlockingQueue<SomeType>();
  fillFromDb(list);
  downloadAndRepopulateList(list);

private void downloadAndRepopulateList(List list) {
new Thread(new Runnable() {
    @Override public void run() {
         list.clear();
        // Some other clode
    }
}
}

LinkedBlockingQueue自己会为你管理同步,你不需要持有任何锁等。

如果您希望使用Arraylist,则必须从两侧使其成为原子。即访问list,他们应该首先锁定对象并继续。如果其他人持有锁,则等待。

synchonized(list){
  fillFromDb(list);
  downloadAndRepopulateList(list);
}


private void downloadAndRepopulateList(List list) {
new Thread(new Runnable() {
    @Override public void run() {
        synhronized(list){
         list.clear();
         }
        // Some other clode
    }
}
}
于 2013-07-22T18:32:03.277 回答
1

要使其工作,您还必须对您的fillFromDb方法进行同步。所以最后你会有两个同步的部分,一个同步你的列表填充,另一个同步清除列表。您也可以将列表用作互斥锁,但我建议您将单独的对象用作互斥锁,我可以像Object mutex = new Object();.

于 2013-07-22T18:30:15.197 回答