Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android listview正在由多线程更新。您看到一个问题_Java_Android_Multithreading - Fatal编程技术网

Java Android listview正在由多线程更新。您看到一个问题

Java Android listview正在由多线程更新。您看到一个问题,java,android,multithreading,Java,Android,Multithreading,可能与我之前发布的问题有关,但这是另一种风格。我有一个列表视图,它带有定制的基底,采用Vector(它过去采用ArrayList,但我把它做成Vector,因为我听说它更安全)。问题是,我有两个线程更新这个向量,结果listview在数据集上更新GUI。如何确保不会发生线程问题?我所做的足够吗 基本适配器类的一部分: public class MyListAdapter extends BaseAdapter { private Vector<Room> roomList

可能与我之前发布的问题有关,但这是另一种风格。我有一个列表视图,它带有定制的基底,采用Vector(它过去采用ArrayList,但我把它做成Vector,因为我听说它更安全)。问题是,我有两个线程更新这个向量,结果listview在数据集上更新GUI。如何确保不会发生线程问题?我所做的足够吗

基本适配器类的一部分:

public class MyListAdapter extends BaseAdapter {


    private Vector<Room> roomList;
    private Context context;


    RoomListAdapter(Context c){
        this.context = c;

    }

    @Override
    public int getCount() { 
        return roomList.size();
    }

    public void setData(Vector<Room> roomData){
        roomList= roomData;
        notifyDataSetChanged();
    }
        @Override
    public Object getItem(int number) {
        return roomList.get(number);
    }

    @Override
    public long getItemId(int arg0) {
        return 0;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

           // Here I get the Room based on position and update my view
       }
}
公共类MyListAdapter扩展BaseAdapter{
专用向量室列表;
私人语境;
RoomListAdapter(上下文c){
this.context=c;
}
@凌驾
public int getCount(){
返回roomList.size();
}
公共无效设置数据(矢量房间数据){
roomList=roomData;
notifyDataSetChanged();
}
@凌驾
公共对象getItem(整数){
返回房间列表。获取(编号);
}
@凌驾
公共长getItemId(int arg0){
返回0;
}
@凌驾
公共视图getView(最终整数位置、视图转换视图、视图组父视图){
//在这里,我根据位置获得房间并更新视图
}
}
同时更新列表的My类具有以下方法:

protected void onCreate(Bundle savedInstanceState) {

    roomVect = new Vector<RoomDataExtra>();
    mylistAdapter = new MyListAdapter(this);
   }
private synchronized void addRoom(Room roomData){
    roomVect.add(roomData);
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            myListAdapter.setData(roomVect);
            listView.setAdapter(myListAdapter);
        }
    });
     }
创建时受保护的void(Bundle savedInstanceState){
roomVect=新向量();
mylistAdapter=新的mylistAdapter(此);
}
私人房间(房间数据){
roomVect.add(roomData);
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
myListAdapter.setData(roomVect);
setAdapter(myListAdapter);
}
});
}
当然,我的线程多次调用addRoom。因此,在列表更新时,我的thead很有可能会调用它。请注意,传递给列表的向量与从列表中更新的向量相同


你认为上面有问题吗?如果有问题,您建议如何解决?

向量实际上并不比这里的任何东西都安全。您需要使用信号量完全阻止所有并发访问。这意味着当某个线程想要更改您的列表时,您需要首先获取一个信号量,然后等待另一个线程完成(完成后放弃该信号量)。您还需要在读取列表的UI端执行此操作,但您必须在读取任何列表之前执行此操作,并在读取完整个列表后将其释放

一种不太复杂的方法是将所有列表更改序列化到UI线程。当想要更改列表的线程需要更改它时,让它向主线程上的处理程序发布Runnable。Runnable将进行实际更改。这样,所有实际的读写操作都将发生在一个线程上。这至少可以避免并发异常,但如果多个索引需要在同一时间进行可视化更改,则无法防止出现问题

如果需要这样做(对多个项目的视觉效果进行同步更改),最好的方法是让更新线程更新列表的深层副本。完成后,将UI正在查看的副本更改为这个新数组,并为更新线程创建一个新的深度副本

TLDR:多线程很难。基于您认为vector确实更安全的事实,您似乎不太了解并发性问题。在尝试使用线程之前,您确实需要学习