threads and GUIs

Discussion in 'Java' started by LC's No-Spam Newsreading account, Nov 17, 2009.

  1. I'm an occasional java programmer for my own utilities. Some applets and
    servlets, and few standalone applications.

    *) standalone with threads is OK

    I've written a test standalone application which happily uses concurrent
    threads (on one hand it pings hosts on the local LAN, on the other it
    retrieves info on which machine is on which slot in a switch, via an
    http connection to the switch itself). This application runs once, does
    most of its task in the main() method and outputs the result to
    terminal.

    Now the next step would be to integrate it with a swing GUI.


    *) standalone with swing is also OK

    The only other swing standalone application I had (and which I routinely
    use), was based on a standard tutorial. Let's call it myClass ...

    - myClass extends JPanel

    - its main method calls javax.swing.SwingUtilities.invokeLater
    to run() a createAndShowGUI() wrapper.

    - the wrapper creates a frame, instantiates a new myGui(), sets
    it as content, and maps the frame

    - myGui generates all the gui with buttons and text areas necessary
    to establish my actions on a mysql database. One of the components
    of the GUI is a JComponent bottom, which ...

    ... is initialized as bottom = new myClass(table) (where table
    is a database table name obtained as args to the main)

    ... it is regularly removed and replaced with a new instance of
    myClass as I continue to issue different mysql queries

    - the constructor myClass manages internally a swing JTable


    *) putting swing and threads together

    In the next step I designed the layout of my new GUI and used
    the same paradigm as above

    - the "monitor" class extends JPanel
    - its main() calls invokeLater to run() a createAndShowGUI() wrapper.
    - the wrapper creates a frame with a new myGui()
    - myGui generates all the gui with buttons etc.

    Now, where should I run my (time-consuming) threads ? So far I
    started with a single thread (the most time-consuming). I was unsure
    whether to put it into a monitor() METHOD or in a new monitor()
    CONSTRUCTOR.

    In the latter case I use a static JComponent dummy; and do
    dummy=new monitor();

    monitor() at some point does a tsw4.start();
    where tsw4 is a static Thread tsw4 = new Thread(sw4);
    and sw4 is an instance of a class which handles the http
    connection. All this defined once forever in the prologue (global
    to my topmost class)

    Anyhow, I can do something of what I want in both cases (method or
    constructor) provided that the invocation of monitor() occurs in the
    main() after a suitable delay (say Thread.sleep(1000);) from the
    deferred creation of the GUI.

    monitor() can run once, and can display its status messages to the
    GUI. I can also use a button to break the thread tsw4 and update
    the status.

    In the future monitor() should become an infinite loop, which
    should run all his threads to completion, display results, wait
    for a programmable interval, and re-run the threads etc.

    The idea is that I could break the threads (which I can already do)
    and then use a button to start a new monitor

    So far my "break" button does :

    tsw4.interrupt();
    dummy=null;

    and my "restart" button does :

    dummy=new monitor();

    Actually I tried to put the dummy=null; soon after the interrupt
    or soon before the new monitor();

    In both cases I get a java.lang.IllegalThreadStateException on the
    tsw4.start(); statement in the monitor() constructor

    but what is the state of the thread ?
    (and why is it illegal ?)

    Note that monitor() does no graphics of its own. I tried also with a
    monitor() method, and to call it in various places, but with obviously
    worse results (e.g. monitor() giving null pointer if GUI start is not
    completed, the GUI waiting to show up until monitor() threads are
    completed, monitor() giving null pointer when trying to write to a
    message area in the GUI, or simply monitor can run once, but a new run
    is ineffective)

    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 17, 2009
    #1
    1. Advertising

  2. LC's No-Spam Newsreading account

    Lew Guest

    LC's No-Spam Newsreading account wrote:
    > I'm an occasional java [sic] programmer for my own utilities. Some applets and
    > servlets, and few standalone applications.
    > ...
    > *) standalone with swing [sic] is also OK
    >
    > The only other swing [sic] standalone application I had (and which I routinely
    > use), was based on a standard tutorial. Let's call it myClass ...


    Class names by convention should begin with an upper-case letter.

    > ...
    > *) putting swing [sic] and threads together
    >
    > In the next step I designed the layout of my new GUI and used
    > the same paradigm as above
    >
    > - the "monitor" class extends JPanel


    Class names by convention should begin with an upper-case letter.

    > - its main() calls invokeLater to run() a createAndShowGUI() wrapper.
    > - the wrapper creates a frame with a new myGui()
    > - myGui generates all the gui with buttons etc.
    >
    > Now, where should I run my (time-consuming) threads ? So far I


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

    > started with a single thread (the most time-consuming). I was unsure
    > whether to put it into a monitor() METHOD or in a new monitor()
    > CONSTRUCTOR.


    Don't start threads from constructors.

    > ...
    > Note that monitor() does no graphics of its own. I tried also with a
    > monitor() method, and to call it in various places, but with obviously
    > worse results (e.g. monitor() giving null pointer if GUI start is not
    > completed, the GUI waiting to show up until monitor() threads are
    > completed, monitor() giving null pointer when trying to write to a
    > message area in the GUI, or simply monitor can run once, but a new run
    > is ineffective)


    Cannot fully answer without <http://sscce.org/>, but I'm betting it has
    something to do with trying to spawn a thread from a constructor.

    All that 'dummy=null' stuff is highly suspicious, too.

    --
    Lew
    Lew, Nov 17, 2009
    #2
    1. Advertising

  3. LC's No-Spam Newsreading account

    markspace Guest

    LC's No-Spam Newsreading account wrote:

    > In both cases I get a java.lang.IllegalThreadStateException on the
    > tsw4.start(); statement in the monitor() constructor
    >
    > but what is the state of the thread ?
    > (and why is it illegal ?)



    Probably because you have already called start() on that thread.
    Threads can only be started once.

    It sounds to me like you still have some concurrency problems.


    >
    > Note that monitor() does no graphics of its own. I tried also with a
    > monitor() method, and to call it in various places, but with obviously



    The problem is that Monitor is a JPanel, which has some implications of
    it's own, i.e., it still needs to be thread safe. Quoting you from some
    stuff earlier in your post:


    > monitor() at some point does a tsw4.start();
    > where tsw4 is a static Thread tsw4 = new Thread(sw4);
    > and sw4 is an instance of a class which handles the http
    > connection. All this defined once forever in the prologue (global
    > to my topmost class)
    >



    This strikes me as a problem. If sw4 truly is an instance, then you are
    almost certainly going to have threading problems. I would make a new
    sw4 instance each time you use it:

    SW4 sw4 = new SW4();
    new Thread( sw4 ).start();

    Not bomb proof, but still more likely to be correct and more robust in
    the long term.


    On a more fundamental level, I think you should be using a SwingWorker.
    This class makes it much easier to write thread safe Swing programs.
    It handles the threading for you so you don't have to. Give your
    Monitor class a "setResult( Object )" method (which does not have to be
    thread safe) and do something like this:


    public class HttpTask extends SwingWorker<Void, Object> {
    @Override
    public Void doInBackground() {
    SW4 sw4 = new SW4();
    sw4.run();
    return null;
    }

    @Override
    protected void done() {
    try {
    monitor.setResult(get());
    } catch (Exception ignore) {
    }
    }
    }

    Now you can call this from anywhere, and it'll be safe(r):

    (new HttpTask()).execute();

    <http://java.sun.com/docs/books/tutorial/uiswing/concurrency/worker.html>

    You also should lay off Thread.sleep(int), which will block the calling
    thread. This is really bad for Swing. Use a Swing Timer instead to do
    your timing tasks.

    <http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html>
    markspace, Nov 17, 2009
    #3
  4. On Tue, 17 Nov 2009, markspace wrote:
    > LC's No-Spam Newsreading account wrote:
    >
    >> In both cases I get a java.lang.IllegalThreadStateException on the
    >> tsw4.start(); statement in the monitor() constructor


    > Probably because you have already called start() on that thread.
    > Threads can only be started once.


    uh ? what happens to a thread when the threaded Runnable run() method
    ends (ends or returns ? is it the same ?)

    > The problem is that Monitor is a JPanel, which has some implications


    but should it be a JPanel in order to display a GUI ?

    monitor.java is an application (therefore it shall contain a class of
    the same name, and a main(). The main uses the standard swing idiom to
    start a GUI. And THEN should execute the workhorse. I am not sure
    whether the workhorse needs to be a constructor (there will be a single
    instance of it), a method with the same name of the class, or a method
    with an arbitrary name. Apparently it does not matter. The workhorse
    does not do GUI-sh things of its own (except updating some gadgets in
    the existing GUI, simplest case is writing messages to a message area).

    >> monitor() at some point does a tsw4.start();
    >> where tsw4 is a static Thread tsw4 = new Thread(sw4);
    >> and sw4 is an instance of a class which handles the http
    >> connection.


    > This strikes me as a problem. If sw4 truly is an instance, then you are
    > almost certainly going to have threading problems. I would make a new sw4
    > instance each time you use it:
    >
    > SW4 sw4 = new SW4();
    > new Thread( sw4 ).start();


    I am not sure if what I mean by instance is the same you mean. At the
    moment this is defined in the prologue, and I have a single object like
    this.

    static SwitchPinger sw4 = new SwitchPinger(4,0,5);

    It is likely that in the future I'll add a new object sw0 with a thread
    of its own.

    static SwitchPinger sw0 = new SwitchPinger(0,6,6);

    I will never have more than two of such. They are a class with a run()
    method which interrogates a switch via http (slowly) using the same
    interrogation procedure. Since we have two switches, I'll never need
    more.

    I'd like to wrap them in a thread, because they are slow. I found than
    running them concurrently with other threads allows me to terminate
    things faster (the other threads are faster but have a timeout (they do
    an ARP ping via an external script), but are many ... I found threads an
    effective way of limiting the number of concurrent ones to a threshold I
    tuned. All this works nicely in a standalone (non-GUI) application.

    > On a more fundamental level, I think you should be using a SwingWorker.
    > <http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html>


    I'll study those two things.


    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 17, 2009
    #4
  5. On Tue, 17 Nov 2009, Lew wrote:

    >> *) putting swing [sic] and threads together


    >> - the "monitor" class extends JPanel

    > Class names by convention should begin with an upper-case letter.


    I thougt the "main" class in an application should have the same name as
    the .java source file. I use upper case (camel case) for directories.
    Anyhow should be irrelevant as far runtime errors are concerned.

    > Don't start threads from constructors.


    I do not want to. I'm not even sure a standalone application like this
    needs a constructor (see reply to other message). Anyhow I have the same
    problems using a constructor, or using a plain method.

    > All that 'dummy=null' stuff is highly suspicious, too.


    That was just a blind attempt. I thought that if I did a repeated
    dummy=new monitor(); I could incur in memory leaks.

    Remember that I have a "break" button which should terminate the threads
    started by monitor(). It does a tsw4.interrupt(); Monitor catches this
    and terminates.

    Then another "restart" button should execute monitor() again. Since it
    is this which gives the error on the thread state, I thought may be it
    had not yet disposed properly of the old monitor().

    Anyhow the current version has no constructor and no dummy. Just calls
    monitor();

    and gives the same problem


    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 17, 2009
    #5
  6. LC's No-Spam Newsreading account

    markspace Guest

    LC's No-Spam Newsreading account wrote:
    > On Tue, 17 Nov 2009, markspace wrote:
    >> LC's No-Spam Newsreading account wrote:
    >>
    >>> In both cases I get a java.lang.IllegalThreadStateException on the
    >>> tsw4.start(); statement in the monitor() constructor

    >
    >> Probably because you have already called start() on that thread.
    >> Threads can only be started once.

    >
    > uh ? what happens to a thread when the threaded Runnable run() method
    > ends (ends or returns ? is it the same ?)



    I don't understand this sentence. However, Runnable doesn't have a
    start() method, and it doesn't throw IllegalThreadStateException, so you
    have a Thread, not Runnable.

    You can't call start() twice on the same Thread. You are. Fix that.


    >
    >> The problem is that Monitor is a JPanel, which has some implications

    >
    > but should it be a JPanel in order to display a GUI ?



    Not necessarily.


    > I am not sure if what I mean by instance is the same you mean. At the
    > moment this is defined in the prologue, and I have a single object like
    > this.
    >
    > static SwitchPinger sw4 = new SwitchPinger(4,0,5);



    Yes, that's an instance. And it's a bad idea. Make this class just
    before you need it.

    SwitchPinger sw4 = new SwitchPinger(4,0,5);
    new Tread( sw4 ).start();

    Don't do this statically. Do it in a method when you need it to happen.

    Also: Java has no "prologue" as far as I know. What you have is called
    a static variable or a class variable. "Prologue" doesn't exist. What
    I want you to use is called a local variable. Please look those terms
    up because they are super important in Java.

    Here's a start:
    <http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html>
    <http://java.sun.com/docs/books/tutorial/java/nutsandbolts/variables.html>

    >
    > It is likely that in the future I'll add a new object sw0 with a thread
    > of its own.
    >
    > static SwitchPinger sw0 = new SwitchPinger(0,6,6);



    SwitchPinger sw4 = new SwitchPinger(0,6,6);
    new Tread( sw4 ).start();

    So? Same as before. Don't do this statically. Don't make this a class
    or instance variable. Use a local variable.

    With no code example, I can't be sure, but this is almost certainly a
    source of potential problems.
    markspace, Nov 17, 2009
    #6
  7. LC's No-Spam Newsreading account

    Lew Guest

    Lew wrote:
    >> Class names by convention should begin with an upper-case letter.

    >


    LC's No-Spam Newsreading account wrote:
    > I thougt the "main" class in an application should have the same name as
    >


    Not just the "main" class but all public classes need to have the same
    basename as the class name, in typical file system-based source /
    class trees. Thus the bytecode for class "FooBar" would be in a file
    "FooBar.class".

    By convention, type, method and variable names are spelled in camel
    case with an initial upper-case letter for types and an initial lower-
    case letter for variables and methods. The exception is constants,
    which are spelled in all upper case.

    These conventions have been in place since Java first started getting
    popular and are well documented on java.sun.com:
    <http://java.sun.com/docs/codeconv/index.html>

    There's some wiggle room on things like opening-brace placement,
    indentation and how to capitalize intialisms like "URL", but the bulk
    of the conventions are pretty universally and rigorously followed.

    > the .java [sic] source file. I use upper case (camel case) for directories.
    >


    Directories correspond to package names. By convention, not quite as
    firm as other naming conventions, packages, and thus directories, are
    spelled with all lower-case letters.

    Lew wrote:
    >> Don't start threads from constructors.

    >


    LC's No-Spam Newsreading account wrote:
    > I do not want to. I'm not even sure a standalone application like this
    > needs a constructor (see reply to other message). Anyhow I have the same


    Every successfully compilable class needs and in fact has a
    constructor whether you write one or not.

    > problems using a constructor, or using a plain method.
    >


    That doesn't mean that starting threads from a constructor is a good
    idea. It just means that you have a different bug, which others in
    this thread have already addressed.

    Lew wrote:
    >> All that 'dummy=null' stuff is highly suspicious, too.

    >


    LC's No-Spam Newsreading account wrote:
    > That was just a blind attempt. I thought that if I did a repeated
    > dummy=new monitor(); I could incur in memory leaks.
    >


    Blind attempts to fix problems tend to bump into walls. Why did you
    think that pointing the 'dummy' reference to different instances would
    incur memory leaks?

    > Remember that I have a "break" button which should terminate the threads
    > started by monitor(). It does a tsw4.interrupt();  Monitor catches this
    > and terminates.
    >
    > Then another "restart" button should execute  monitor() again. Since it
    > is this which gives the error on the thread state, I thought may be it
    > had not yet disposed properly of the old monitor().
    >


    As others have stated, you cannot restart a thread that has
    terminated. That results in an 'IllegalThreadStateException '.

    > Anyhow the current version has no constructor and no dummy. Just calls
    >      monitor();
    >
    > and gives the same problem
    >


    You say that as if we could somehow magically read your mind to know
    what's in or not in your code.

    Do not ignore <http://sscce.org/>, previously recommended. How do you
    expect anyone to give meaningful answers when you don't give any
    relevant details?

    GIGO: Garbage in, garbage out. If you don't give good data, you can't
    get good answers.

    --
    Lew
    Lew, Nov 17, 2009
    #7
  8. LC's No-Spam Newsreading account

    Lew Guest

    LC's No-Spam Newsreading account wrote:
    > uh ? what happens to a thread when the threaded Runnable
    > run() method ends (ends or returns ? is it the same ?)


    It just hangs around until and unless all references to it go away. Once a
    thread object is dereferenced in your code and is no longer alive, it becomes
    eligible for garbage collection (GC).

    When a method ends, it returns.

    LC's No-Spam Newsreading account wrote:
    > monitor.java is an application (therefore it shall contain a class of
    > the same name, and a main(). The main uses the standard swing [sic] idiom to
    > start a GUI. And THEN should execute the workhorse. I am not sure
    > whether the workhorse needs to be a constructor (there will be a single


    The phrasing "be a constructor" is inapplicable. Your "workhorse" will be an
    instance of a class, which must be constructed before it can be used.

    > instance of it), a method with the same name of the class, or a method
    > with an arbitrary name. Apparently it does not matter. The workhorse


    It does matter. First of all, there should not be any method with the same
    name as the owning class; that's a recipe for confusion with constructors.
    Second, it is dangerous to spawn threads from inside a constructor. Memory
    visibility is not guaranteed until the constructor completes. The only safe
    option is to spawn a thread from a method invoked after construction is
    complete (and with a different name from the class's constructors).

    > does not do GUI-sh things of its own (except updating some gadgets in
    > the existing GUI, simplest case is writing messages to a message area).


    "Does not do X except for Y" means "Does do X". The doublespeak increases the
    risk of bugs in your code.

    > I am not sure if what I mean by instance is the same you mean. At the


    The term "instance" has a well-defined and particular meaning in
    object-oriented programming, and in Java specifically. It means an object
    constructed on the heap. At the bottom, you obtain an instance by
    constructing it (using a 'new' expression), and access it through a reference
    to that instance.

    markspace wrote:
    >> On a more fundamental level, I think you should be using a SwingWorker.


    Link to the Javadocs can be found upthread.

    >> <http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html>


    LC's No-Spam Newsreading account wrote:
    > I'll study those two things.


    You might consider also reviewing the online Java tutorials and the Java
    Language Specification (JLS) for the details of types and instances and how
    they're constructed and referenced.

    --
    Lew
    Lew, Nov 18, 2009
    #8
  9. On Tue, 17 Nov 2009, markspace wrote:

    >> uh ? what happens to a thread when the threaded Runnable run()
    >> method ends (ends or returns ? is it the same ?)


    > I don't understand this sentence.


    Apparently Lew did understand it, and gave a reply meaningful and useful
    for me.

    > You can't call start() twice on the same Thread. You are. Fix that.


    That something I did not realize. I imagined that start() will invoke
    the run() method of the thread "argument", and that when that
    terminated, the thread could be started again. I even tested
    tsw4.isAlive() [in order to write a idle/running message in a text
    label] before start, after start, and after a tsw4.join() and imagined
    that "alive" or not could be the only status.

    > Also: Java has no "prologue" as far as I know. What you have is
    > called a static variable or a class variable. "Prologue" doesn't
    > exist. What I want you to use is called a local variable.


    The concept of local and global are known to me, although my background
    from 30 years of Fortran (hope that doesn't make you laugh) tend to
    privileges local variables unless things are in COMMON blocks. What I
    (improperly) called "prologue" is the list of class variables defined in
    the source file after the first class statement and before main(),
    eventual constructors or other methods, which are global not only to the
    "main" class but also to its other inner classes. Remember that I'm
    writing standalone applications.

    >> static SwitchPinger sw4 = new SwitchPinger(4,0,5);

    >
    > Yes, that's an instance. And it's a bad idea. Make this class just
    > before you need it.


    I thought that doing an instance of SwitchPinger each time (with the
    idea to run things in a loop, currently instead iterations beyond the
    first are activated manually) would somehow waste memory.

    > SwitchPinger sw4 = new SwitchPinger(4,0,5);
    > new Tread( sw4 ).start();


    > Don't do this statically. Do it in a method when you need it to happen.


    Done it (in fact the original non-GUI version did exactly that).
    This gets rid of the IllegalThreadStateException

    But I cannot use a pure local variable. I do instead

    static Thread tsw4=null; // in the prologue :)

    Then in the workHorse (which is a method and not a constructor, I have
    no explicit constructors now) I do

    SwitchPinger sw4 = new SwitchPinger(4,0,5);
    tsw4 = new Thread(sw4);
    tsw4.start();

    I need tsw4 to be global, since the GUI shall define an action for a
    "break" button which does

    tsw4.interrupt();

    Possibly I'd still have to look in SwingWorker. Or finally do a SCCE,
    which I hoped to avoid, since I'm just inserting bit by bit into the
    swing application code which did work in a non-swing one.

    At present what happens is the following :

    - main calls invokeAndWait for the wrapper which does the GUI
    (I replaced invokeLater followed by a sleep(1000) with this)
    - main calls workHorse()

    the first loop runs OK, and can be also interrupted pressing the
    "break" button I put in the GUI

    - the restart button runs again workHorse()

    this runs OK (before it gave the IllegalThreadStateException), but
    while running locks the GUI (the restart button "remains depressed"
    and all the other buttons do not react), which means de facto the
    thread is not interruptable

    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 18, 2009
    #9
  10. (part. OT) names Re: threads and GUIs

    On Tue, 17 Nov 2009, Lew wrote:

    > Not just the "main" class but all public classes need to have the same
    > basename as the class name, in typical file system-based source /
    > class trees. Thus the bytecode for class "FooBar" would be in a file
    > "FooBar.class".


    Please remember that I'm an occasional java programmer (scientist with
    [long] Fortran programming background). I'd hardly write general purpose
    reusable classes (alike to libraries of subroutines for me). What I
    usually need are standalone applications with a main() and few other
    methods. So I'd have a single myapp.java source file (with inner classes
    if I find convenient or I'm forced to put thing in other classes).

    >> I use upper case (camel case) for directories.

    >
    > Directories correspond to package names.


    I was not thinking of java development (I know what they are, and put my
    hands on things which a younger programmer wrote for me). I was mainly
    thinking of "everyday's life".

    For me a directory contains things related to a project, a satellite, a
    celestial source, a paper, a software package (oy yes :)) etc. And are
    these names which I put with capital initials.

    Files can be program sources or executables, shell scripts, tex sources,
    data files, plain text, other documents etc. And for these I use
    lowercase. All uppercase is only for README or alike :)


    > Every successfully compilable class needs and in fact has a
    > constructor whether you write one or not.


    The "typical application" I'm thinking of is a standalone main(). So if
    I know I can avoid to write a constructor for something which will
    exist in a single instance, I will.

    > That doesn't mean that starting threads from a constructor is a good
    > idea.


    I've taken note.

    > Do not ignore <http://sscce.org/>, previously recommended.


    As I said, I hoped to avoid it since I already had a working non-swing
    standalone app, and a dummy swing app with just the GUI. I wanted to
    "reverse" bits by bits pieces from the main() of the non-swing one into
    some appropriate method of the new app.

    But I cannot come to an end soon, I will do a SSCCE.

    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 18, 2009
    #10
  11. Thanks Re: threads and GUIs

    On Tue, 17 Nov 2009, markspace wrote:

    > On a more fundamental level, I think you should be using a SwingWorker.


    Read a bit about it (luckily I have a java6 since a while) and
    implemented a wrapper according to your suggestion ...

    > (new HttpTask()).execute();


    .... although I used a different name

    > Give your Monitor class a "setResult( Object )" method


    .... done with a totally dummy one

    public static void setResult( Object o) { }

    > public class HttpTask extends SwingWorker<Void, Object> {


    the only modification is that I had to add "static"
    public static class ...

    to prevent compile error "non-static variable this cannot be
    referenced from a static context" on
    ( new TheRealStuffIsHere()).execute();

    With the replacement of the invocation of workHorse() with the above
    statement both in the main() after GUI setup (for the first iteration),
    or in the code activated by the reload button (for subsequent
    iterations), now the method which contains the threads can run in all
    cases, and can be interrupted by break in all cases !

    Thanks !

    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 18, 2009
    #11
  12. LC's No-Spam Newsreading account

    Lew Guest

    LC's No-Spam Newsreading account wrote:
    > I thought that doing an instance of SwitchPinger each time (with the
    > idea to run things in a loop, currently instead iterations beyond the
    > first are activated manually) would somehow waste memory.


    Java manages memory for you. When an instance no longer has any references to
    it reachable from the live program, i.e., the instance becomes unreachable, it
    is eligible for garbage collection (GC) to delete it.

    In a loop like:

    for ( Item item : stuff )
    {
    Foo foo = new Foo();
    foo.process( item );
    }

    a new 'Foo' is created within each iteration of the loop. Clearly there are
    no other references to that new instance (unless 'process()' does something
    weird - we'll assume not). As each loop iteration closes, the 'foo' reference
    goes out of scope and the 'Foo' instance becomes unreachable. GC will
    eventually collect and destroy the unreachable references if it thinks the
    memory is needed.

    Java is optimized for short-lived objects, ones that become unreachable
    quickly. If the 'Foo' instance were created outside the loop and refilled
    each time, the loop could be slower and memory pressure would likely increase,
    not decrease. That's because Java GC uses different strategies for short- and
    long-lived objects.

    Java doesn't actually have memory leaks. What we Java folks call "leaks" are
    actually the opposite - memory references that are not released, leaving
    objects still reachable, ergo uncollectible, eventually causing the dreaded
    'OutOfMemoryError' ("OOME" colloquially).

    As in paths to inner peace, the guiding principle for harmonious object
    management in Java is, "Let it go."

    --
    Lew
    Lew, Nov 18, 2009
    #12
  13. LC's No-Spam Newsreading account

    Roedy Green Guest

    You are asking for very specific help with your code without revealing
    the code itself. If the code is too long to post, post it on the
    Internet somewhere and post a URL. If you have not got a place to post
    it, just ask and likely someone here can accommodate you.

    For some background information, in case you missed something, see
    http://mindprod.com/jgloss/swingthreads.html
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com

    Without deviation from the norm, progress is not possible.
    ~ Frank Zappa (born: 1940-12-21 died: 1993-12-04 at age: 52)
    Roedy Green, Nov 18, 2009
    #13
  14. LC's No-Spam Newsreading account

    Lew Guest

    Lew wrote:
    > GC will eventually collect and destroy the unreachable
    > references


    Urp. I meant unreachable *instances*.

    > if it thinks the memory is needed.


    --
    Lew
    Lew, Nov 18, 2009
    #14
  15. LC's No-Spam Newsreading account

    Lew Guest

    Re: Thanks Re: threads and GUIs

    markspace wrote:
    >> public class HttpTask extends SwingWorker<Void, Object> {


    LC's No-Spam Newsreading account wrote:
    > the only modification is that I had to add "static"
    > public static class ...
    >
    > to prevent compile error "non-static variable this cannot be
    > referenced from a static context" on
    > ( new TheRealStuffIsHere()).execute();


    You had another choice - to create an instance of the enclosing class and
    invoke the inner-class constructor through that instance. It is likely that
    your approach to make the nested class 'static' rather than inner was the
    correct one.

    There are times when it's better to make a nested class inner (non-'static'),
    such as to give access to members of the enclosing class instance.

    --
    Lew
    Lew, Nov 18, 2009
    #15
  16. LC's No-Spam Newsreading account

    markspace Guest

    LC's No-Spam Newsreading account wrote:

    >
    > Apparently Lew did understand it, and gave a reply meaningful and useful
    > for me.



    I'm glad because I honestly didn't understand it (and still don't, really).


    >> You can't call start() twice on the same Thread. You are. Fix that.

    >
    > That something I did not realize. I imagined that start() will invoke



    It's clearly documented but it's also a "gotcha." Lot's of folks miss it.


    > The concept of local and global are known to me, although my background
    > from 30 years of Fortran (hope that doesn't make you laugh) tend to
    > privileges local variables unless things are in COMMON blocks. What I



    This could be a bit of an issue. Java prefers to pass arguments to
    methods rather than using globals; Java technically doesn't even have
    globals, you use class variables instead. Trying to use "globals" is
    one of the more difficult things you can do with multi-threaded
    programming.


    > SwitchPinger sw4 = new SwitchPinger(4,0,5);
    > tsw4 = new Thread(sw4);
    > tsw4.start();



    This global still bugs me. When does this happen? Can the user kick
    off two such threads? What happens in that assignment to tsw4 if
    there's already a tsw4 running?

    Rather than just one holder for a single thread, you might want to look
    into using a Executor as your "global," or something like a synchronized
    List or Map. Both of those are thread safe and might avoid some of the
    problems you are having.


    >
    > I need tsw4 to be global, since the GUI shall define an action for a
    > "break" button which does
    >
    > tsw4.interrupt();



    Again, how many such "tsw4" threads could possibly be running at one
    time? Do you restrict them to exactly one? Where and how?


    >
    > Possibly I'd still have to look in SwingWorker. Or finally do a SCCE,
    > which I hoped to avoid, since I'm just inserting bit by bit into the
    > swing application code which did work in a non-swing one.
    >
    > At present what happens is the following :
    >
    > - main calls invokeAndWait for the wrapper which does the GUI
    > (I replaced invokeLater followed by a sleep(1000) with this)
    > - main calls workHorse()
    >
    > the first loop runs OK, and can be also interrupted pressing the
    > "break" button I put in the GUI
    >
    > - the restart button runs again workHorse()



    Yeah, here I think you could be running two threads at once, if you
    aren't careful.


    >
    > this runs OK (before it gave the IllegalThreadStateException), but
    > while running locks the GUI (the restart button "remains depressed"
    > and all the other buttons do not react), which means de facto the
    > thread is not interruptable
    >



    Locking the GUI happens because you are running your task inside the GUI
    thread itself, so the GUI can't be updated. Using a Thread should
    alleviate that, if done properly.

    You can use what you have now, I think, if you are very careful. Don't
    allow the user to click "restart" until they click "break" and the
    (single, global) thread has terminated.

    Also, every time you touch tsw4, you must synchronize on some common
    object. You are sharing this object between two threads (as near as I
    can tell) and access is not threads safe. Traditionally, for class
    variables one synchronizes on the class itself.

    public class MyMain {

    private static Thread tsw4;

    public static void workHorse() {
    synchronize( MyMain.class ) {
    // safe now, use the same "synchronize" statement when the gui
    // accesses this variable too

    if( tsw4 != null && tsw4.isAlive() ) {
    System.err.out( "error, tsw4 already in use..." );
    return;
    }

    // ok to make a new thread here...

    }
    }
    }

    I'm thinking though this would be easier if tsw4 were a SwingWorker
    instead of a simple Thread. There's also probably better ways of
    structuring this overall, if I had more time to think about it.
    markspace, Nov 18, 2009
    #16
  17. LC's No-Spam Newsreading account

    markspace Guest

    Re: Thanks Re: threads and GUIs

    LC's No-Spam Newsreading account wrote:

    > With the replacement of the invocation of workHorse() with the above
    > statement both in the main() after GUI setup (for the first iteration),
    > or in the code activated by the reload button (for subsequent
    > iterations), now the method which contains the threads can run in all
    > cases, and can be interrupted by break in all cases !



    Good, I'm glad you got it sorted. I posted another reply upthread
    before I read this post, there still might be some useful information
    for you.

    I don't discount the possibility of further multi-threading issues,
    however that SwingWorker is 90% thread safe and should keep you out of
    the worst troubles.
    markspace, Nov 18, 2009
    #17
  18. On Wed, 18 Nov 2009, markspace wrote:
    > LC's No-Spam Newsreading account wrote:


    > This global still bugs me. When does this happen? Can the user kick
    > off two such threads?


    > Again, how many such "tsw4" threads could possibly be running at one
    > time? Do you restrict them to exactly one? Where and how?


    In principle the user should not do this, unless by mistake. There are
    easy ways out of this, like disabling/enabling the buttons
    conditionally, or using some form of lock boolean variable (the CGI this
    application is going to replace used a lock file).

    Most important, I will be THE (only) user of this application !

    > Also, every time you touch tsw4, you must synchronize on some common object.


    I'll re-read the part of the tutorial on synchronization.

    > I'm thinking though this would be easier if tsw4 were a SwingWorker
    > instead of a simple Thread.


    As you already realized from my later replies, a SwingWorker wrapping
    my entire work horse routine seems to do what I want nicely

    --
    ----------------------------------------------------------------------
    is a newsreading account used by more persons to
    avoid unwanted spam. Any mail returning to this address will be rejected.
    Users can disclose their e-mail address in the article if they wish so.
    LC's No-Spam Newsreading account, Nov 19, 2009
    #18
  19. I am not sure if what I mean by instance is the same you mean. At the
    moment this is defined in the prologue, and I have a single object
    like
    this.

    static SwitchPinger sw4 = new SwitchPinger(4,0,5);

    It is likely that in the future I'll add a new object sw0 with a
    thread
    of its own.

    static SwitchPinger sw0 = new SwitchPinger(0,6,6);

    I will never have more than two of such. They are a class with a run()
    method which interrogates a switch via http (slowly) using the same
    interrogation procedure. Since we have two switches, I'll never need
    more.

    I'd like to wrap them in a thread, because they are slow. I found than
    running them concurrently with other threads allows me to terminate
    things faster (the other threads are faster but have a timeout (they
    do
    an ARP ping via an external script), but are many ... I found threads
    an
    effective way of limiting the number of concurrent ones to a threshold
    I
    tuned. All this works nicely in a standalone (non-GUI) application.
    Teraposa Lunodas, Nov 24, 2009
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. V e X y N

    GUIs and Compilers.. <help>

    V e X y N, Aug 22, 2003, in forum: C Programming
    Replies:
    2
    Views:
    370
    Greg P.
    Aug 22, 2003
  2. Jay  Eichelberger

    Matlab, GUIs and Cygwin

    Jay Eichelberger, Nov 15, 2003, in forum: Python
    Replies:
    1
    Views:
    372
    John Hunter
    Nov 16, 2003
  3. Christopher Culver

    OO design, Python, and GUIs

    Christopher Culver, Nov 18, 2003, in forum: Python
    Replies:
    3
    Views:
    399
    Alan Gauld
    Nov 18, 2003
  4. j_mckitrick

    Encapsulation and GUIs

    j_mckitrick, Jun 8, 2004, in forum: Python
    Replies:
    0
    Views:
    280
    j_mckitrick
    Jun 8, 2004
  5. Glen Holcomb

    Of GUIs threads and scheduling woes

    Glen Holcomb, Jul 23, 2008, in forum: Ruby
    Replies:
    11
    Views:
    196
    Glen Holcomb
    Jul 25, 2008
Loading...

Share This Page