Re: How to stop a thread?

Discussion in 'Java' started by John C. Bollinger, Aug 27, 2003.

  1. Lee Francis Wilhelmsen wrote:
    > Hi
    >
    > I have a mathematical algorithm that takes a while to complete. It runs in
    > it's own thread. To stop the thread I interrupt the thread and then set the
    > thread variable to null. The following code has been adapted from the
    > program and is presented in the following class. The Worker class that does
    > the work isn't really relevant here.


    On the contrary, the details of the worker class are very relevant.

    > class MyClass {
    > private Thread t = null;
    >
    > public void go() {
    > SwingUtilities.invokeLater(new Runnable() {
    > public void run() {
    > MyClass.this.t = new Thread() {
    > public void run() {
    > // the work is done in the worker
    > Worker worker = new Worker():
    > worker.doWork();
    > }
    > }
    > }
    > }
    > }
    >
    > public void quit() {
    > // user want to interrupt operation
    > if (MyClass.this.t != null) {
    > MyClass.this.t.interrupt();
    > MyClass.this.t = null;
    > }
    > }
    > }
    >
    > Does this look ok?


    No.

    In the first place, take SwingUtilities out of the picture. To start a
    new Thread just instantiate it and invoke its start() method. That's
    not a problem even in a Swing / AWT event handler. If that thread wants
    to manipulate the GUI, then it should use SwingUtilities to insert those
    manipulations into the AWT event handling thread.

    In the second place, you should need to qualify "this" with MyClass,
    especially in your quit() method.

    > I'm having trouble getting the Worker.doWork() algorithm
    > to terminiate it's operation?


    Is that a question?

    In the third place, I'm not surprised if you are having trouble getting
    Worker.doWork() to terminate. As I said above, it's details are very
    relevant to the question. Interrupting a Thread sets a flag in that
    Thread's state, but there are only a few methods in the entire platform
    API that are directly affected (Thread.sleep() and Object.wait() being
    two of the more relevant ones). If you want your algorithm to be
    interruptible then you have to code for it.

    > I'm thinking fairly general here. The
    > algorithm contains a loop. Should each iteration check Thread.interrupted()
    > and break if true? Should it throw an InterruptedException? Both (depending
    > the thread state)


    A looping algorithm is the easiest kind for which to enable
    interruption. Once for every n iterations (n >= 1) you check the
    current thread's interrupted status and terminate if it is set. There
    are multiple ways to do that. One way is to insert a Thread.sleep(1);
    this will throw an InterruptedException if the current Thread has been
    interrupted, and it will also ensure that other Threads in the JVM have
    a chance to run. You can also check Thread.interrupted() or
    Thread.currentThread.isInterrupted() [be careful, the semantics are
    slightly different] to obtain the current Thread's interrupted status at
    any time.

    It is not necessary to throw an exception when the thread is
    interrupted, but if you want it to stop then you must make sure that its
    run method terminates. That can happen normally or via an exception.

    Although Java provides the Thread.interrupt() mechanism, it is also
    possible to create a similar feature by defining your own flag to be set
    when execution is supposed to terminate.

    >
    > This is what I'm using today and it isn't working.


    Very likely you are either interrupting the wrong Thread or your
    interruption checking is incorrect. Or it _is_ working and you have a
    different problem than you think you do. Show us the appropriate part
    of Worker's code if you want a real analysis. Even better, develop a
    complete, cut down example that demonstrates your problem.

    As an aside, it would be more elegant if Worker implemented Runnable;
    then you wouldn't need a separate, anonymous Runnable. Furthermore, you
    should probably take measures against your calculation being started
    multiple times, because you only keep track of the Thread of the most
    recent one.


    John Bollinger
    John C. Bollinger, Aug 27, 2003
    #1
    1. Advertising

  2. > On the contrary, the details of the worker class are very relevant.

    Yes, but I was talking about the actual algorithm. :) Sorry for any
    confusion.

    > In the first place, take SwingUtilities out of the picture. To start a
    > new Thread just instantiate it and invoke its start() method. That's
    > not a problem even in a Swing / AWT event handler. If that thread wants
    > to manipulate the GUI, then it should use SwingUtilities to insert those
    > manipulations into the AWT event handling thread.


    The algorithm updates a UI model for a progress bar. I thought I needed to
    run the code in SwingUtilities.invokeLater(). So what you are saying is move
    this invokeLater call to the actual code updating the progress bar model? I
    didn't want to clutter the algorithm with call to UI code.

    > In the second place, you should not need to qualify "this" with MyClass,
    > especially in your quit() method.


    Why is that a problem? Is it a problem or just a preference?

    > In the third place, I'm not surprised if you are having trouble getting
    > Worker.doWork() to terminate. As I said above, it's details are very
    > relevant to the question. Interrupting a Thread sets a flag in that
    > Thread's state, but there are only a few methods in the entire platform
    > API that are directly affected (Thread.sleep() and Object.wait() being
    > two of the more relevant ones). If you want your algorithm to be
    > interruptible then you have to code for it.


    Ok, the application running this algorithm is a GUI with a start and stop
    button. When the user presses the stop button then the quit() code is
    called. What you are saying is that it's unessessary and I should instead
    implement a worker.stop() method or something. I guess, that means that the
    worker must be referenced in the class and implement the Runnable interface.

    > > I'm thinking fairly general here. The
    > > algorithm contains a loop. Should each iteration check

    Thread.interrupted()
    > > and break if true? Should it throw an InterruptedException? Both

    (depending
    > > the thread state)

    >
    > A looping algorithm is the easiest kind for which to enable
    > interruption. Once for every n iterations (n >= 1) you check the
    > current thread's interrupted status and terminate if it is set. There
    > are multiple ways to do that. One way is to insert a Thread.sleep(1);
    > this will throw an InterruptedException if the current Thread has been
    > interrupted, and it will also ensure that other Threads in the JVM have
    > a chance to run. You can also check Thread.interrupted() or
    > Thread.currentThread.isInterrupted() [be careful, the semantics are
    > slightly different] to obtain the current Thread's interrupted status at
    > any time.


    This is what I'm doing (Thread.interrupted), but it never returns true. The
    loop also calls a Thread.yield().

    > > This is what I'm using today and it isn't working.

    >
    > Very likely you are either interrupting the wrong Thread or your
    > interruption checking is incorrect. Or it _is_ working and you have a
    > different problem than you think you do.


    Well I have verified that the thread is the same. I give the thread a name
    and ask for it's name before a call to isInterrupted() or interrupt() is
    made.

    > Show us the appropriate part of Worker's code if you want a real analysis.

    Even better, develop a
    > complete, cut down example that demonstrates your problem.


    Ok, I'll try:

    public class Worker {
    public void doWork(String[] domains) throws InterruptedException {
    try {
    doThis();
    }
    catch(Throwable e) {
    logger.severe("Unknown exception in worker " + e.getMessage());
    throw new InterruptedException(e.getMessage());
    }

    private void doThis() throws InterruptedException {
    for (some iterations) {
    Thread.yield();
    ....
    if (Thread.interrupted())
    throw new InterruptedException("Reporting interrupted");
    }
    }
    }

    > As an aside, it would be more elegant if Worker implemented Runnable;
    > then you wouldn't need a separate, anonymous Runnable. Furthermore, you
    > should probably take measures against your calculation being started
    > multiple times, because you only keep track of the Thread of the most
    > recent one.


    But what if the code was already implemented and I had no control over it.
    Should I create an Adapter class that implements a Runnable interface?
    Should the worker have implemented Runnable from the start? I would have
    preferred to keep threading issues out of the main algorithm so I can test
    it easier (with JUnit etc). However, I see this can't be done if I want it
    to be able to quit before it's finished.

    Regards
    Lee Francis
    Lee Francis Wilhelmsen, Aug 28, 2003
    #2
    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. Matt Theule

    Stop Debugging doesn't stop in ASP.NET

    Matt Theule, Jul 23, 2003, in forum: ASP .Net
    Replies:
    7
    Views:
    733
    Matt Theule
    Jul 24, 2003
  2. Son KwonNam
    Replies:
    11
    Views:
    2,601
    mr_organic
    Apr 9, 2004
  3. Will
    Replies:
    1
    Views:
    15,234
    Thomas Weidenfeller
    Nov 2, 2004
  4. Benji
    Replies:
    34
    Views:
    1,174
    pkriens
    Oct 28, 2005
  5. Angus
    Replies:
    5
    Views:
    451
    Ben Bacarisse
    Jul 18, 2010
Loading...

Share This Page