Possible easy diagnostic outputting from multiple threads to the onetext frame

J

jc_usernet

Hello.
I'm back into JAVA again and am curious to know the response from the
clever JAVA community about
my wish for an "easy diagnostic outputting from multiple threads to
the one text frame".

My current solution that I would like to improve on is:
-------------------------------------------------------
// DiagnosticOutput.java
// Class DiagnosticOutput updates JTextArea with output
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DiagnosticOutput extends JFrame {
private JTextArea outputArea;
// the constructor
public DiagnosticOutput ( )
{
super( "Demonstrating Product & Consumer Thread" );

outputArea = new JTextArea( 20, 30 );
outputArea.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) );
this.getContentPane().add( new JScrollPane( outputArea ) );

// set some properties of the "this" object
this.setSize( 555, 500 );
this.setVisible( true );

this.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
}

// this is the method for the writing the data to the JFrame
public void put( String messageToAppend )
{
// invokeLater i understand is the thread safe way of running
the
// run method of the runnable object that is passed as a
parameter.
// Note that the runnable object also has the JTextArea object
and the
// message to append as parameters to it's constructor.
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
messageToAppend ) );
}
} // end class
-------------------------------------------------------
This seems to do what I want for now. However it find this wanting
since I always have to create
an object and pass the reference around to all the participating
objects.

Is it possible to have a class without the need to explicitly create a
object for the output I want?
I am thinking along the lines of a static method like
DiagnosticOutput.put( String stringToAppend )
and first time usage creates the object and subsequent usage appends
to this hidden (from the application)
object. So all I need do is simply invoke this method at the various
location within the application.

Regards JC....
 
L

Lew

Your code seems good but you neglect to call 'pack()'. Also your
example is incomplete, but I'll assume the omitted parts are not
important.

jc_usernet said:
I'm back into JAVA again and am curious to know the response from the

It's spelled "Java".
My current solution that I would like to improve on is:

These comments should have been in a Javadoc comment.

[snip]
This seems to do what I want for now.  However it find this wanting
since I always have to create an object
and pass the reference around to all the participating objects.

Why is this a problem?
Is it possible to have a class without the need to explicitly create a
object for the output I want?

Anything's possible.
I am thinking along the lines of a static method like
DiagnosticOutput.put( String stringToAppend )

Static methods are particularly dangerous in a multi-threaded context
such as the one you need this for.
and first time usage creates the object and subsequent usage appends

Lazy initialization is fraught with peril and usually provides no
benefit.
to this hidden (from the application)
object.  So all I need do is simply invoke this method at the various
location within the application.

No, that's not all you need do. You also will need to add a bunch of
careful synchronization and spend a lot of time debugging the result
when it turns out that the use of static methods, a static object,
lazy initialization and multiple threads causes either or both of
wrong results or a huge performance bottleneck.
 
M

markspace

jc_usernet said:
I am thinking along the lines of a static method like
DiagnosticOutput.put( String stringToAppend )


What I would do here is use the logging framework. Make a Handler that
writes to a JTextArea. Then you can control writes and even
instantiation more easily just by using the normal logging configuration
properties.

Here's an example. This class is, I believe, thread-safe, although
quite simple.


class TextAreaHandler extends Handler {

private final JTextArea view;

public TextAreaHandler( JTextArea view )
{
this.view = view;
}

@Override
public void publish( LogRecord record )
{
view.append( record.getMessage() );
view.append( '\n' );
}

@Override
public void flush()
{
// no-op
}

@Override
public void close()
{
// possibly dispose the top-level window here
}

}
 
L

Lew

markspace said:
Here's an example.  This class is, I believe, thread-safe,
although quite simple.

class TextAreaHandler extends Handler {

    private final JTextArea view;

    public TextAreaHandler( JTextArea view )
    {
       this.view = view;
    }

    @Override
    public void publish( LogRecord record )
    {
       view.append( record.getMessage() );
       view.append( '\n' );
    }

    @Override
    public void flush()
    {
       // no-op
    }

    @Override
    public void close()
    {
       // possibly dispose the top-level window here
    }



}

I worried about the 'view.append()' actions seeming not to be on the
EDT until I looked at the Javadocs for 'JTextArea#append()':
"This method is thread safe, although most Swing methods are not.
Please see _Threads and Swing_ for more information."
 
J

John B. Matthews

Lew said:
I worried about the 'view.append()' actions seeming not to be on the
EDT until I looked at the Javadocs for 'JTextArea#append()': "This
method is thread safe, although most Swing methods are not. Please
see _Threads and Swing_ for more information."

As a convenience when invoking append() form another thread, the
DefaultCaret update policy may be set to ALWAYS_UPDATE in order to
cause the text area to scroll automatically.

<http://java.sun.com/javase/6/docs/api/javax/swing/text/DefaultCaret.html>

This article elaborates:

<http://tips4java.wordpress.com/2008/10/22/text-area-scrolling/>
 
M

markspace

The documentation is wrong, as has been discussed already years ago, mostly
in comp.lang.java.gui


You appear to be correct. How odd.

Even ignoring problems with mutual exclusion and stuff happening "at the
same time", the calls append() and setText() make no attempt at
synchronization or any sort of happens-before relationship. The
underling call to Document.insert isn't noted to be thread safe either,
so I don't know what prompted the Swing team to mark this method as
thread safe.

(OTOH, the underlying Document doesn't have the usual Swing note about
not being thread safe, so perhaps the entire class is thread safe. Not
sure. There's nothing on thread safety documented at all for Document,
either way.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top