3

I've written the class VideoProcessor, which does some heavy processing on a video. If "started", a new Thread is created and the reference is saved in the field videoProcessingThread. The problem now is:

videoProcessingThread.interrupt();

This does not seem to have any effect, as isInterrupted() never evaluates to true. I also added other interrupt checks, just to be sure; but they don't "work" either. I've implemented a workaround:

videoProcessingThread.kill();

This seems to actually "kill" the thread. The method kill sets the boolean variable kill to true and that is evaluated correctly and the Thread returns.

videoProcessingThread = new Thread() {
    boolean kill = false; // workaround 

    public void run() {
        // init stuff
        while (currentFrameIndex < totalFrames) {
            if (isInterrupted()) { 
                System.out.println("isInterrupted");

                return;
            }
            if (Thread.interrupted()) {
                System.out.println("interrupted");

                return;
            }
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Thread.currentThread().isInterrupted()");

                return;
            }
            if (kill) {
                System.out.println("killed");

                return;
            }
        }
        // heavy processing
    }

    public void kill() {
        kill = true;
    }
}

What am I doing wrong?

joschi
  • 12,746
  • 4
  • 44
  • 50
einerlei
  • 33
  • 3
  • 1
    Have you reviewed http://stackoverflow.com/questions/8627719/interrupt-doesnt-work? – ziesemer Jan 22 '12 at 08:35
  • is heavy processing (or any method called there) catching an InterruptedException or checking the interrupted flag? – user85421 Jan 22 '12 at 09:27
  • How can you invoke a method that is declared by an anonymous class? In other words, 'videoProcessingThread' is Thread, which doesn't have a kill method. How do you call it? Bit of a tangent, but just curious. – erickson Jan 22 '12 at 10:02

2 Answers2

1

Your kill is not guaranteed to work, unless its volatile.

A thread is only interrupted when an operation which checks this flag is called. Some NIO operations with throw an exception if you call interrupt()

Most of the time using interrupt() is the same as setting a volatile flag. i.e. your task needs to check it regularly. The only safe way to kill a thread is to run it in its own process.

If you have a thread which is an Actor (it only modifies thread local memory) you could consider using stop(). The main problem with it is you can leave memory the thread modified in an inconsistent state. If you isolate the memory for that thread and discard it if the thread is stopped this should work fine.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    @Tudor, Perhaps its because I mentioned stop() which is deprecated, but that doesn't mean you can't use it if you know what you are doing. – Peter Lawrey Jan 22 '12 at 09:46
  • 1
    I agree that stop() is a bad idea most of the time, but if the code executed by the thread has no way of leading to inconsistent state then I don't see the problem either. – Tudor Jan 22 '12 at 09:53
1

First of all, calling interrupt() may not actually set the interrupted status, please see here in javadocs the exact conditions, sometimes it will just throw an InterruptedException.

Second, actually calling the interrupted() method will also clear the interrupted status in addition to returning it, so the next call to isInterrupted() (which only returns the current status, but does not clear it) may not do what you expect.

Using a boolean variable is probably not a bad method to accomplish this. You can read this article which goes into some details to clarify what exactly happens when you try to interrupt a thread and how to do it more or less reliably.

ivantod
  • 773
  • 3
  • 8