线程的中断条件java
- 当线程的run方法执行方法中的最后一句话后,并由return语句返回时,线程结束 2. 或是在线程中出现了没有捕获的异常时,线程将终止 3. interrupt方法能够用来请求终止线程 interrupt
- 为何要用interrupt来中断线程,在什么状况下用 interrupt是用来强制中断那些出于阻塞状态(sleep,join,wait)的线程,阻塞状态的线程被调用interrupt时会抛出InterruptException 的错误,而后退出阻塞状态,这个错误要被catch才行。 若是线程再调用interrupt时,不处于阻塞状态,则在线程进入阻塞状态时,会抛出InterruptException
- interrupt 说明 主要来讲明下interrupt,若是对一个线程调用interrupt方法时,线程的中断状态将被置位,也就是改变线程的中断状态,由于每一个线程都有一个boolean标志,每一个线程都会不时的检查标志来判断是否被中断。
public class threadInterrupt {异步
public static void main(String[] args) { final Thread aThread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block System.out.println(" thread a throw interruptException "); } } }); aThread.setName("aaaaaaaaaa"); Thread bThread = new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub System.out.println("interrupt 前的中断标志"+aThread.isInterrupted() ); aThread.interrupt(); System.out.println("interrupt 后的中断标志"+aThread.isInterrupted() ); } }); aThread.start(); bThread.start(); }
}socket
图片中能够看到在调用interrupt前的false ,调用interrupt后是true 并抛出了interruptExceptionide
static boolean interrupted() 用来测试线程是否被中断,可是会将线程的中断状态改成false boolean isInterrupted() 也是用来测试线程是否被终止,但不会改变中断状态函数
###对中断操做的正确理解 调用interrupt 并不意味着当即中止目标线程在进行的工做,而只是传递了请求中断的消息,而后由线程在下一个合适的时刻中断本身。例如wait、slepp和join等,当他们接收到中断请求或者在开始执行时发现某个已经被设置好的中断状态时,将抛出一个异常。 > 一般中断是实现取消的最合理方式测试
例如用下面两个例子来讲明,为何中断是取消的最合理的方式 (1)首先是不采用中断的方式来取消,加入下面queue的长度是5,在添加第6个元素时,queue.put()会产生阻塞,因此在以后的时间里,线程是不会去检测cancelled的标志,因此任务永远也不会结束,这样就没法取消了this
class BrokenPrimeProducer extends Thread { private final BlockingQueue<BigInteger> queue; private volatile boolean cancelled = false; BrokenPrimeProducer(BlockingQueue<BigInteger> queue) { this.queue = queue; } public void run() { try { BigInteger p = BigInteger.ONE; while (!cancelled) queue.put(p = p.nextProbablePrime()); } catch (InterruptedException consumed) { } } public void cancel() { cancelled = true; } }
(2)下面这个是用中断来取消,由于Thread.sleep、Object.wait或BlockingQueue.put等阻塞函数都会检查线程合适中断,而且发现中断就提早返回,执行的操做包括清楚中断状态,抛出InterruptedException。在阻塞操做前检查线程的阻塞状态能够提升对中断操做的响应。线程
public class PrimeProducer extends Thread { private final BlockingQueue<BigInteger> queue; PrimeProducer(BlockingQueue<BigInteger> queue) { this.queue = queue; } public void run() { try { BigInteger p = BigInteger.ONE; while (!Thread.currentThread().isInterrupted()) queue.put(p = p.nextProbablePrime()); } catch (InterruptedException consumed) { /* Allow thread to exit */ } } public void cancel() { interrupt(); } }
线程任务的取消
一般,使用现有库中的类逼本身编写的来取消线程任务要来的更好,英雌咱们应该用Future来取消一个线程任务。code
public class TimedRun { private static final ExecutorService taskExec = Executors.newCachedThreadPool(); public static void timedRun(Runnable r, long timeout, TimeUnit unit) throws InterruptedException { Future<?> task = taskExec.submit(r); try { task.get(timeout, unit); } catch (TimeoutException e) { // 任务将被取消 } catch (ExecutionException e) { // 若是在任务中抛出了异常,那么从新抛出该异常 throw LaunderThrowable.launderThrowable(e.getCause()); } finally { // 若是任务已经结束,那么执行取消操做也不会带来什么影响 task.cancel(true); // interrupt if running } } }
对于不可中断阻塞的处理
对于某些线程阻塞操做,并不会抛出InterruptedException 例如某些I/O操做和内部锁操做图片
- Java.io包中的同步SocketI/O. 读写socket的时候,InputStream和OutputStream的read和write方法会阻塞等待,但不会响应java中断。不过,调用Socket的close方法后,被阻塞线程会抛出SocketException异常。
- Selector实现的异步I/O 若是线程被阻塞于Selector.select(在java.nio.channels中),那么调用wakeup或close方法会引发ClosedSelectorException异常。
- 获取某个锁 若是一个线程因为等待某个内置锁而阻塞,那么将没法响应中断,由于线程认为它确定会得到锁,因此不会理会中断请求。