Java 在DefaultListModel与ConcurrentHashMap中存储数据

Java 在DefaultListModel与ConcurrentHashMap中存储数据,java,swing,jlist,concurrenthashmap,defaultlistmodel,Java,Swing,Jlist,Concurrenthashmap,Defaultlistmodel,我正在swing中编写GUI以显示来自客户端的输入请求。服务器填充一个LinkedBlockingQueue,当有数据可用时,另一个线程从队列中获取数据。请求存储为对象。像这样: while(should_take) { //getRequest() is blocking Object request = server.getRequest(); //Add request to user interface GUI.addToList(request); }

我正在swing中编写GUI以显示来自客户端的输入请求。服务器填充一个
LinkedBlockingQueue
,当有数据可用时,另一个线程从队列中获取数据。请求存储为
对象
。像这样:

while(should_take) {
    //getRequest() is blocking
    Object request = server.getRequest();

    //Add request to user interface
    GUI.addToList(request);
}
现在我的问题是,是否最好:

解决方案1:

请求
存储在
ConcurrentHashMap
中,键作为请求的哈希,值作为对象。然后,我将使用
DefaultListModel
存储请求的标识符(例如请求类型)和散列值。
DefaultListModel
将用于填充
JList
,有效地向用户显示请求。然后,可以使用保存在
DefaultListModel
中的哈希从ConcurrentHashMap检索所选请求的值(由用户选择)

一些示例代码:

ConcurrentHashMap<Integer, Object> requests = new ConcurrentHashMap<>();
DefaultListModel listData = new DefaultListModel();
JList theList = new JList();
...
public void addToList(Object request) {
    //Place in HashMap
    requests.put(request.hashCode(), request);

    //Create a DataHolder with the Hashvalue and identifier of the request
    DataHolder holder = new DataHolder(request.getID(), request.hash);

    //Add the element to the ListModel
    listData.addElement(holder);

    //Assign the list model to the JList
    theList.setModel(listData);
}
DefaultListModel listData = new DefaultListModel();
JList theList = new JList();
...
public void addToList(Object request) {
    //Removed HashMap

    //Create a DataHolder with the Hashvalue and *actual value* of the request
    DataHolder holder = new DataHolder(request.getID(), request);

    //Add the element to the ListModel
    listData.addElement(holder);

    //Assign the list model to the JList
    theList.setModel(listData);
}
解决方案2:

我用请求标识符和请求值填充一个新对象,称之为
DataHolder
。现在,我可以使用包含
DataHolder
DefaultListModel
填充
JList
,并且不需要引用任何其他数据结构来检索实际请求值。由于
DefaultListModel
用于填充
JList
,我觉得这会影响性能,并可能导致列表填充/取消填充速度变慢

一些示例代码:

ConcurrentHashMap<Integer, Object> requests = new ConcurrentHashMap<>();
DefaultListModel listData = new DefaultListModel();
JList theList = new JList();
...
public void addToList(Object request) {
    //Place in HashMap
    requests.put(request.hashCode(), request);

    //Create a DataHolder with the Hashvalue and identifier of the request
    DataHolder holder = new DataHolder(request.getID(), request.hash);

    //Add the element to the ListModel
    listData.addElement(holder);

    //Assign the list model to the JList
    theList.setModel(listData);
}
DefaultListModel listData = new DefaultListModel();
JList theList = new JList();
...
public void addToList(Object request) {
    //Removed HashMap

    //Create a DataHolder with the Hashvalue and *actual value* of the request
    DataHolder holder = new DataHolder(request.getID(), request);

    //Add the element to the ListModel
    listData.addElement(holder);

    //Assign the list model to the JList
    theList.setModel(listData);
}
当用户选择列表中的项目时:

DataHolder holder = (DataHolder)theList.getSelectedValue();
//Get request from HashMap

Object request = requests.get(holder.getHash());
//Do something with request
//No more HashMap
DataHolder holder = (DataHolder)theList.getSelectedValue();

Object request = holder.getData();
//Do something with request
哪种解决方案会产生更快的结果?有没有更有效的方法?在此问题上的任何帮助都将不胜感激

更多信息:

  • 请求可能会以突发方式发送。(每脉冲50+次)
  • 请求将由20到50行XML组成
  • 请求将随机从数据结构中删除
编辑:

将消息添加到列表的序列现在已包装在
invokeLater
中。在我的实现中,每次将消息添加到列表中时,都会创建一个新线程来完成所有工作,并在消息进入列表后结束。这肯定会影响答案如果连续创建50个线程(每次调用addToList),哪个解决方案执行得更快?解决方案3:Extend

class MessageWorker扩展SwingWorker{}

doInBackground()
的实现中,
publish()
中间结果可用时。在
process()
的实现中,更新视图组件的模型。方便的是,
SwingWorker
将在一个时间点合并
publish()
调用。您的应用程序需要验证。可以找到更多的示例。

更简单的方法是使用DefaultListModel,特别是在有更改的情况下……,请注意,Swing、GUI.addToList(请求)的输出中存在一致性问题;要Swing,必须将方法包装到invokeLater@mKorbel谢谢你解决了我都不知道的问题!!我的GUI有时会不同步,所以我限制了传入请求的速率。这永久地修复了它。非常感谢(您的编辑)DefaultListModel完全是MVC,不管线程是如何调用的(实际上并不重要),但所有信号都应该在一个地方结束,在模型(DefaultListModel)中,运行时没有添加/删除/插入的问题(50个线程中的任何内容),问题是,如果用户主动使用JLists视图,那么您必须通过覆盖ListSelectionEvents来使用AbstractListModel(可以基于任何数组,请注意HashXxx),如果您想在JList视图中使用选择,请更正我的错误,但是StringWorker本质上不就是利用
线程
可运行
并允许干净地访问所有精彩的线程功能吗?我确实实现了这一点,现在可以在更新列表的同时访问列表,这很好。看来你在某种程度上支持解决方案2?我想你的意思是我应该在
MessageWorker
中填充
DefaultListModel
,并在再次访问删除它时?虽然可以使用其他方法,但
SwingWorker
通过
Runnable
Future
RunnableFuture
PropertyChangeEvent
提供了更多功能;您应该仅在EDT上更新
列表模型
,例如在
过程中();除了速度之外,还可以让工作人员调整视图更新的速度,从而使视图更生动;当有东西要看时,用户可以更好地等待。谢谢,我实现了所有功能,解决方案3获得了金牌