Question

I am writing a GUI in swing to display incomming requests from clients. The server populates a LinkedBlockingQueue, while another thread takes from the queue when there is data available. The requests are stored as an Object. Like so:

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

    //Add request to user interface
    GUI.addToList(request);
}

Now my question comes in, would it be better to:

Solution 1:

Store the request in a ConcurrentHashMap<Integer, Object> with the key as the hash of the request and the value as the Object. I will then use a DefaultListModel to store the identifier (eg. request type) of the request and the hash value. The DefaultListModel will be used to populate a JList, effectively displaying the request to the user. The value of the selected request (selected by the user) can then be retrieved from the ConcurrentHashMap using the hash saved in the DefaultListModel.

Some example code:

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);
}

When a user selects an item in the list:

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

Object request = requests.get(holder.getHash());
//Do something with request

Solution 2:

I populate a new Object, call it DataHolder, with the request identifier and request value. I can now populate the JList with DefaultListModel that contains DataHolder and no reference is needed to any other data structure to retrieve the actual request value. Because DefaultListModel is used to populate the JList, I feel it can impact performance and may cause the list to populate/unpopulate slower.

Some example code:

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);
}

When a user selects an item in the list:

//No more HashMap
DataHolder holder = (DataHolder)theList.getSelectedValue();

Object request = holder.getData();
//Do something with request

Which solution will yield quicker results? Is there a more efficient way to do this? Any help on the matter will be greatly appreciated.

Some more info:

  • Request may be delivered in bursts. (50+ per burst)
  • Requests will consist of between 20 and 50 lines of XML
  • Requests will be removed from the data structure randomly

EDIT:

The sequence that adds messages to the list has now been wrapped in invokeLater. With my implementation, every time a message will be added to the list, a new thread will be created to do all the work, and end once the message is in the list. Surely this effects the answer. If 50 threads are created in tight succession (with each call to addToList), which solution will execute quicker?

Was it helpful?

Solution

Solution 3: Extend SwingWorker,

class MessageWorker extends SwingWorker<List<DataHolder>, DataHolder> {}

In your implementation of doInBackground(), publish() intermediate results as they become available. In your implementation of process(), update the view component's model. Conveniently, SwingWorker will coalesce publish() invocations at a sustainable pace. Profile your application to verify. More examples may be found here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top