Java并发(四):终结任务

Java并发(四):终结任务

一、线程状态与线程进入阻塞的原因
线程的休眠sleep()最终将唤醒,而任务也将返回原线程。但是sleep()一种情况是,它使任务从执行状态变为阻塞状态,而有时必须终止被阻塞的任务

  1. 线程状态
    一个线程可以处于以下四种状态之一:
     新建(new):当线程被创建时,它只会短暂地处于这种状态,此时它已经分配了必需的系统资源,并执行了初始化
     就绪(Runnable):在这种状态下,只要调度器把时间片分配给线程,线程就可以运行。
     阻塞(Blocked):线程能够运行,但有某个条件阻止了它的运行
    死亡(Dead):处于死亡或者终止状态的线程将不再是可调度的,并且再也不会得到CPU时间。
  2. 线程进入阻塞状态的原因
     通过调用sleep使任务进入休眠状态,在这种情况下,任务在指定的时间内不会运行。
     通过调用wait()使线程挂起,直到线程得到notify()或notifyAll()消息,线程才会进入就绪状态。
     任务在等待某个输入/输出完成
     任务试图在某个对象上调用其同步控制方法,但是对象锁不可以用,因为另一个任务已经获取这个锁。

二、中断
Thread类包含了一个interrupt()方法,该方法可以终止被阻塞的任务,这个方法将设置线程的中断状态。通过调用一个线程的interrupt()方法来中断该线程,如果该线程处于阻塞、限期等待或者无限期等待状态,那么就会抛出InterruptedException,从而提前结束该线程。但是不能中断I/O阻塞和synchronized阻塞,这意味着I/O以及synchronized具有锁住多线程程序的潜在可能。
在这里插入图片描述
使用Executor的线程管理的线程,调用Executor的shutdown()方法会等待线程都执行完毕之后再关闭,但是如果调用的是shutdownNow()方法,则相当于调用每个线程的interrupt()方法
在这里插入图片描述
如果想要中断Executor中的一个线程,可以通过submit()方法来提交一个线程,它会返回一个Future<?>对象,通过调用该对象的cancel(true)方法即可中断线程
在这里插入图片描述
如前面所述,只要任务以不可中断的方式被阻塞,那么就有潜在的会锁住程序的可能。Java SE5并发类库中添加了一个特性,即在ReentrantLock上阻塞的任务具备可以被中断的能力,这与在synchronized方法或临界区上阻塞的任务完全不同。
在这里插入图片描述

三、检查中断
如果一个线程的run()方法执行一个无限循环,并且没有执行sleep()等会抛出异常InterruptedException的操作,那么调用该线程的interrupt()方法就无法使线程提前结束
但是调用interrupt()方法会设置线程的中断标记,此时调用interrupted()方法会返回true。因此可以在循环体中使用interrupted()方法来判断线程是否处于中断状态,从而提前结束线程。
在这里插入图片描述
需要注意的是,调用interrupted()方法能够检查中断状态,但是同时会清楚中断状态
在这里插入图片描述

参考资料:《Java编程思想》
CS-Notes/Java 并发.md

原创文章 78 获赞 25 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_38196407/article/details/90036994