Posting on the SwingEventThread

Hi.

I have an application that is receiving reatime updates on a seperate thread to the EventQueue. These realtime updates will result in a JTable being updated somehow (add/delete/update etc.)

On receiving the realtime update I need to post the actual swing updates onto the EventQueue (SwingEventThread). I do this like so...

publicvoid realTimeUpdate(final Object someData)

{

SwingUtitlities.invokeLater(new Runnable()

{

publicvoid run()

{

doRealTimeUpdate(someData)

}

}

}

Standard stuff....However I am getting a few realtime updates per second, resulting in a new anonymous class (the Runnable) being created each time. This is not really a problem but the GC will be forced to run a lot more than I would like.

So, the question I have is as follows:

Is there a better way than creating a new Runnable() each time. I have toyed with the idea of using a pool of Runnables but that can then become a bottleneck and block the receive thread.

What is the overhead of creating the anonymous class each time?

Any thoughts/ideas....

nes

[1507 byte] By [dr_nessa] at [2007-10-2 11:02:10]
# 1

You can create a class level field worker

and use it. For example:

class A {

private Runnable runnable = new Runnable() {

public void run() {

doRealTimeUpdate(someData)

}

};

public void realTimeUpdate(final Object someData) {

SwingUtitlities.invokeLater(runnable);

}

}

sklimenkoa at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...
# 2
hmm.How do you pass in the data to be run from from the Runnable (i.e. someData) and how do you guarantee that the Runnable has finished running before reassigning?nes
dr_nessa at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...
# 3

Where'is two ways:

1. You idea is correct

2. You can organize your own FIFO (first input first output) buffer and put your objects to it. In this way class will be look like following:

class A {

private Buffer buffer = new Buffer();

public void realTimeUpdate(final Object someData) {

buffer.executeObject(someData);

}

private class Buffer implements Runnable {

private LinkedList queue = new LinkedList();

public void executeObject(Object o) {

queue.addLast(o);

SwingUtilities.invokeLater(this);

}

public void run() {

doRealTimeUpdate(queue.removeFirst());

}

}

}

P.S. LinkedList is optimazed for FIFO.

sklimenkoa at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...
# 4

As a general rule, if you don't have a performance issue then you shouldn't be optimising ;)

I would guess that the creation of a new Runnable is minor compared to the impact that your event is likely to have on the application. Don't take my word for it - profile your code and find out whether it's worth trying to improve things.

You could obviously use some sort of collection (FIFO as shown above) to hold your data and a reusable Runnable could take the latest data from it (or even process all the data at once).

I'm not sure I entirely agree with the suggestion of using a LinkedList since adding an element involves the instantiation of a new LinkedList.Entry - you might as well have just instantiated a new Runnable in the first place and you wouldn't need to mutate a list! Again, profiling would identify this.

In some situations it's safe to assume that only the latest data is relevant. You can therefore reuse a single Runnable which uses the latest data received, enqueuing that Runnable only when it isn't currently pending execution already.

You can even engineer this situation by having a (pooled) Runnable for each partition of your data. For example, if your updates are the prices for exchange rates you could have one Runnable for each currency pair since you only care about the latest data for each.

Personally I don't think it's worth optimising until you've profiled and identified that creation of a new Runnable is where it's worth getting clever.

Hope this helps.

KPSeala at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...
# 5

Interesting replies. I will take a look at what you suggest sklimenko and get back to you.

KPSeal, I understand where you are coming from and generally I don't optimize unless I have to (which isn't very often ;p). However when I see my object count going through the roof when profiling I tend to get a little nervous. I understand that the creation of the anonymous Runnable is acceptable, but I am more concerned about triggering a lot more GC's due to my heap being used up a lot quicker.

I was just interested in whether anybody else had encountered this issue (or even deemed it as one!).

I'll let you know what I decide once I have put the profiler through its paces....

nes

dr_nessa at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...
# 6

I have one more idea. You can put your own events in system queue:

public void realTimeUpdate(final Object someData) {

EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();

queue.postEvent(new Job());

}

private static final class Job extends InvocationEvent implements Runnable {

Job() {

super(Toolkit.getDefaultToolkit(), null);

runnable = this;

}

public void run() {

doRealTimeUpdate(someData);

}

}

When you call SwingUtilities.invokeLater(Runnable) new InvocationEvent is created. But you also creates new Runnable object each time.

In my case you just creates only one object - event that do your own job. So number creating object will less.

What do you think about it?

sklimenkoa at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...
# 7
Thanks to both of you. 1 duke each.
dr_nessa at 2007-7-13 3:33:37 > top of Java-index,Desktop,Core GUI APIs...