2012-11-24 24 views
8

我使用下面的代码时,得到IllegalThreadStateException例外: 我已经开始这个线程一次(使用thread.start()),并再次试图在另一个地方启动它,因此使用下面的代码:停止线并重新开始给IllegalThreadStateException黑莓

thread.interrupt(); 
thread.start(); 

thread.start()抛出IllegalThreadStateException

我应该用什么来解决它?

+1

刚刚添加了'java'标签,因为它对任何'java'都很常见。 –

回答

16

Thread对象只能启动一次。如果您需要停止/中断Thread,然后想再次启动它,你应该创建一个新的实例,并在其上调用start()

thread.interrupt(); // if you need to make sure thread's run() method stops ASAP 
thread = new MyThreadSubclass(); 
thread.start(); 

From the API docs

IllegalThreadStateException - 如果线程已经启动。

我知道这是不是100%清楚,你不能再打电话start(),即使您以前叫interrupt(),但是这是它的工作方式。

如果你看看API docs for standard Java,这个问题更加清楚。

+0

谢谢Nate。但是当我试图使用'thread.interrupt();' 它再次显示异常为 - ** IllegalThreadStateException **。 – AnkitRox

+0

@AnkitRox,API文档不显示'interrupt()'抛出任何异常。不过,我猜测你甚至在第一次运行这段代码之前就调用了interrupt()。你真的只需要中断线程,如果它已经启动一次。所以,你想调用'start()'的第二,第三等时间,你可以事先调用'interrupt()'。你可以在调用'thread.interrupt()'之前测试'thread.isAlive()'。如果这不起作用,则需要显示更多代码(例如,如何创建Thread对象)。 – Nate

+0

我有一个类'AsyncUploadQuestionsAndLeads',它由'Thread'扩展。 使用初始化Thread对象: 'AsyncUploadQuestionsAndLeads uploadThread =新AsyncUploadQuestionsAndLeads(事件);' 而从其他地方启动线程: 'uploadThread.start();' 一段时间后,我使用代码如下: 'uploadThread.interrupt(); uploadThread.start();' 这是我遵循的代码过程。 还有一个问题是 - 当线程完成它的运行块时线程是否自行停止? – AnkitRox

7

除了Nate的回答。

在他的评论AnkitRox状态:

感谢奈特。我也在尝试你的方法。但那时发生的问题是,它为新实例启动了一个新线程,并且之前的线程也在工作。

所以看起来这个问题是“线程仍在运行,即使我呼吁它的中断”。考虑这个样本(这是丑陋的,但足以显示其主要思想):

final Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (true) { 
      for (int i = 0; i < 100000000; i++); // simulate some action 
      System.out.println("hi, interrupted = " 
        + Thread.currentThread().isInterrupted()); 
     } 
    } 
}); 
t.start(); 
new Timer(true).schedule(
    new TimerTask() { 
     public void run() { 
      t.interrupt(); 
     } 
    }, 
    1000 // 1 second delay 
); 

注意,线程继续运行interrupt()被称为甚至后。产生的输出是:

hi, interrupted = false 
hi, interrupted = true 
hi, interrupted = true 
hi, interrupted = true 
... 
hi, interrupted = true 

实际上,程序永远不会停止,除非强制关闭。那么interrupt()是做什么的?它只是将中断标志设置为true。在interrupt()之后被称为Thread.currentThread().isInterrupted()开始返回false。就这样。

另一种情况是,如果interrupt()被称为同时线程被阻塞在抛出InterruptedException,则该方法将返回投掷InterruptedException的方法之一的调用。如果线程的代码只是“吃”这一例外,那么线程仍然会继续运行,考虑一个例子:

final Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (true) { 
      System.out.println("hi, interrupted = " 
        + Thread.currentThread().isInterrupted()); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) { 
       System.out.println("got InterruptedException"); 
      } 
     } 
    } 
}); 
t.start(); 
new Timer(true).schedule(
    new TimerTask() { 
     public void run() { 
      t.interrupt(); 
     } 
    }, 
    1000 // 1 second delay 
); 

注意,线程继续运行interrupt()被称为甚至后。产生的输出是:

hi, interrupted = false 
got InterruptedException 
hi, interrupted = false 
hi, interrupted = false 
... 
hi, interrupted = false 

注意,此时interrupted = falseinterrupt()被称为甚至后。这是因为每当InterruptedException被捕获时,中断标志被重置为false

在Java中停止线程是合作机制。这意味着如果没有线程本身的合作,就无法完成。下面是上述样品的固定的版本:

final Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (!Thread.currentThread().isInterrupted()) { 
      System.out.println("hi, interrupted = " 
        + Thread.currentThread().isInterrupted()); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) { 
       System.out.println("we've been interrupted"); 
       // restore the interrupted flag 
       Thread.currentThread().interrupt(); 
      } 
     } 
    } 
}); 
t.start(); 
new Timer(true).schedule(
    new TimerTask() { 
     public void run() { 
      t.interrupt(); 
     } 
    }, 
    1000 // 1 second delay 
); 

所以,正确的做法应该是定期检查中断标志。如果检测到中断状态,则只需返回ASAP。另一个常见选项是根本不使用Thread.interrupt(),但是some custom boolean instead

+0

很好的解释。并不丑陋:) – Nate