中断睡眠线程

时间:2011-08-22 08:30:32

标签: java multithreading interrupt

尝试中断正在运行的线程,在本例中为t1,由线程池中的线程执行。

t2是发送中断的那个。

我无法停止正在运行的t1,t1没有得到InterruptedException。

我错过了什么?

    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();

5 个答案:

答案 0 :(得分:3)

好像你误解了线程和执行者。您为两个runnable创建两个线程对象,但只启动其中一个(t2),t1传递给Executor在其中运行。但是执行程序不需要提供Thread - 它只需要Runnable实现。 Executor本身是一个线程池(通常,但它不是必需的),它只是在其中创建(和池)线程。它看到你的线程就像Runnable一样简单(这是Thread实现的)。因此,您实际上将中断发送到从未启动过的线程。

如果你真的想让你的代码工作,你应该删除Executor,然后显式启动两个线程。

答案 1 :(得分:3)

您的错误是您尝试在Thread上执行ThreadPool

出现,因为Thread碰巧实现了Runnable,但因为该线程仅用作Runnable而未启动为一个Thread,调用#interrupt()等方法将无法达到预期的效果。

如果您仍然需要使用线程池,则应考虑使用类似FutureTask的类。将Runnable包裹在FutureTask中,然后将任务提交到线程池。然后,当您想要中断任务时,请致电futureTask.cancel(true)

答案 2 :(得分:1)

问题是你永远不知道Executor将使用哪个线程来运行你的任务。

即使您提交了Thread对象,执行程序也将使用固定线程池创建的线程。因此,引用t1的线程不是您的任务将在其中执行的线程。所以调用t1.interrupt()不会做任何事情。

要正确地执行此操作,请使用ExecutorService并使用submit()提交Runnable / Callable个对象。这将返回Future,其中公开了cancel()方法,该方法可用于取消任务。

答案 3 :(得分:0)

要中断执行程序线程,

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

答案 4 :(得分:0)

调用Thread.interrupt不一定会抛出InterruptedException。它可能只是设置线程的中断状态,可以通过Thread.interrupted()或Thread.isInterrupted进行轮询。

有关详细信息,请参阅http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt()。