Archive for July, 2007

Stupid fast hyperlinks for Swing

July 13th, 2007 | Carl

Co-authored by Huey.

HyperLinkLabel screen shot
Most people who’ve done a little preliminary looking online will learn that to create a component that functions like a hyperlink the easiest way is to use a JEditorPane. If you use the HTMLEditorKit you can introduce hyperlinks, they’ll render appropriately, and you can even add a HyperlinkListener. There’s just one drawback. It’s a little slow to instantiate. Alternatively, you can pass html to a JLabel, which will render the hyperlink, then add a mouse listener, but that’s not much faster. Besides that, the JEditorPane doesn’t seem to alter the mouse when you mouseover an active link. Sloppy. So I wrote HyperlinkLabel.

Try out the Web Start HyperlinkLabel Demo | Download executable jar + source

Take a look at these numbers for 1000 instantiations of a configured class:

JEditorPane: 1922 ms, 1906 ms, 1922 ms = Average 1916 ms
JLabel: 1250 ms, 1250 ms, 1234 ms = Average 1244 ms
HyperlinkLabel: 62 ms, 62 ms, 63 ms = Average 62.3 ms

Read on for more details. Read the rest of this entry »

SimpleDateFormat is not thread-safe

July 11th, 2007 | Allen

It seems like a relatively common mistake is to assume that the java.text.SimpleDateFormat class is thread-safe (at least for methods such as format(), which you might not expect to mutate state!). This is not true; SimpleDateFormat is not thread-safe, and format() does mutate state. From the javadoc:

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

Suggestions on handling synchronization:

private final static ThreadLocal<SimpleDateFormat> shortTimeFormat =
     new ThreadLocal<SimpleDateFormat>() {
            protected SimpleDateFormat initialValue() {
                 return new SimpleDateFormat("HH:mm");
             }
      };

N.B. In general, you should be very careful when using ThreadLocal storage, especially when using thread pools (your data won’t be automatically garbage collected and may be visible to other Threads—a security risk) or when storing references to Thread objects in ThreadLocal storage (which might confuse the GC). However, in this case, we should be okay.


Palantir