[concurrency-interest] Confused about Component.getTreeLock()

Gregg Wonderly gregg at cytetech.com
Wed Mar 7 09:56:09 EST 2007



Peter Kovacs wrote:
>>ordering controls to make sure that another thread doesn't MESS with the state
>>of the components preferredSize()
> 
> Do "ordering controls" mean "synchronization" here?

It means inter-thread ordering that spans threads and time.  Drawing on the 
example that I was using before:

Swing's text highlighting is very slow when rendering and scrolling large 
amounts of highlighted text.

We needed a data tracing window that showed sent and received text, coloring 
each differently.  So, we implemented a faster highlighter using a JPanel inside 
of a scrollpane.  The JPanel has to be sized as new text arrives.  After the 
resize, you need to compute the location that the scrollbar should move to and 
move it.  Because of the EDT.invokeLater() calls calls involved in some of the 
logic, you have to use invoke later for everything.  Because each invokeLater() 
is a separate runnable, you have to keep order between their activities and 
subsequent arriving text which can queue new Runnables inbetween others.

private void newText( String str, boolean sent ) {
	list.add( new TextElement( str, sent ) );
	synchronized( lock ) {
		if( working )
			return;
		working = true;
	}

	// Figure out how tall we are now for scrollbar adjustments
	Dimension sz = computeSize();

	// We are usually not in the EDT
	runInSwing( new Runnable() {
		public void run() {
			// Change the panel size to fit all
			// of the text.
			panel.setPreferredSize( sz );
		}
	});

	// This causes an invokeLater() to revalidate, so now
	// everything else that depends on time ordering must run
	// via invokeLater().
	panel.revalidate();

	// Render all the text into the panel
	panel.repaint();

	// Queue the scrollbar positioning because the
	// revalidate and repaint are queued above,
	// not run in line.
	SwingUtilities.invokeLater( new Runnable() {
		public void run() {
			try {
				scrollToEnd();
			} finally {
				working = false;
			}
		}
	});
}

Now, this particular style of ordering with a shared "lock", is perilous because 
you can't use any language guarentees to make sure that working is set back to 
false, no matter what happens.

We had to defer updates that were competing for scrollbar position changes 
because if we didn't, there are troublesome interactions because diferrent 
threads are putting things into the EDT queue.

Gregg Wonderly


More information about the Concurrency-interest mailing list