开发者

Interrupt a sleeping thread

Trying to interrupt a running thread, in this example, t1, which is executed by a thread in a thread pool.

t2 is the one that sends the interrupt.

I'm unable to stop the running t1, t1 does not get Interrupte开发者_如何学运维dException.

What am I missing?

    Executor exec1 = Executors.newFixedThreadPool(1);

    // task to be interrupted
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                System.out.println("starting uninterruptible task 1");
                Thread.sleep(4000);
                System.out.println("stopping uninterruptible task 1");
            } catch (InterruptedException e) {
                assertFalse("This line should never be reached.", true);
                e.printStackTrace();
            }               
        }           
    };
    final Thread t1 = new Thread(runnable);


    // task to send interrupt
    Runnable runnable2 = new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                t1.interrupt();
                System.out.println("task 2 - Trying to stop task 1");
                Thread.sleep(5000);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }               
        }           
    };
    Thread t2 = new Thread(runnable2);

    exec1.execute(t1);
            t2.start();
    t2.join();


Seems like you misunderstand threads and Executors. You create two threads object for two runnables, but start only one of them (t2), t1 you pass to Executor to run inside it. But executor does not need Thread to be supplied -- it just need Runnable implementation. Executor itself is a thread pool (usually, but it's not required), and it just creates (and pool) threads inside it. It sees you thread just as simple Runnable (which is Thread implements). So you actualy send interrupt to the thread which was never started.

If you really want to make your code works, you should remove Executor, and just start both threads explicitly.


Your mistake is that you're trying to execute a Thread on a ThreadPool.

This appears to work, because Thread happens to implement Runnable, but because the thread is only being used as a Runnable and is not started as a Thread, calling methods like #interrupt() won't have the desired effect.

If you still need to use a thread pool, you should instead look into using a class like FutureTask. Wrap your Runnable in a FutureTask, and then submit the task to a thread pool. Then, when you want to interrupt the task, call futureTask.cancel(true).


The problem is that you can never really know which thread would be used by the Executor to run your task.

Even though you have submitted a Thread object, The Executor will use the thread created by the fixed thread pool. Thus the thread with reference t1 is not the thread in which your task is going to be executed. so calling t1.interrupt() is not going to do anything.

To properly way to do this is to use an ExecutorService and use the submit() to submit a Runnable/Callable object. This will return a Future which exposes a cancel() method which can be used to cancel the task.


Calling Thread.interrupt does not necessarily throw an InterruptedException. It may just set the interrupted state of the thread, which can be polled by Thread.interrupted() or Thread.isInterrupted.

See http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt() for more details.


To interrupt the executor thread ,

final ExecutorService exec1 = Executors.newFixedThreadPool(1);
final Future<?> f = exec1.submit(runnable);
...
f.cancel(true);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜