[Java并发编程实战] 第7章 取消与关闭

任务取消
  • 每个线程有一个boolean类型的中断状态,中断线程时被置为true;静态的interrupted方法将清除当前线程的中断状态,并返回它之前的值,这是清除中断状态的唯一方法

  • 阻塞库方法(Thread.sleep/Object.wait)会检查线程何时中断,发现中断提前返回:清除中断状态、抛出InterruptedException。

  • 当线程在非阻塞状态下中断时,它的中断状态将被设置,然后根据将被取消的操作来检查中断状态以判断发生了中断。通过这样的方法,中断操作将变得“有黏性”——如果不触发InterruptedException,中断状态将一直保持,直到明确地清除中断状态

  • 任务应该包含取消策略,线程应该包含中断策略,线程应该只能由其所有者中断;通常,中断是实现取消的最合理方法;在中断线程之前,应该了解它的中断策略

  • Thread的join的不足:无法直到执行控制是因为线程正常退出而返回还是因为join超时而返回

  • Future的cancel方法:如果任务已经结束,那么执行取消操作也不会带来任何影响;如果任务正在执行,将被中断

  • 不可中断的阻塞

    • Java.io包中的同步Socket I/O、Java.io包中的同步I/O、Selector的异步I/O、获取某个锁

    • 中断请求只能设置线程的中断状态,阻塞方法不会检查中断状态,然后提前返回或抛出异常

    • 改写执行不可中断操作的线程的interrupt方法,解决使线程阻塞的原因(如关闭socket连接等),然后调用super.interrupt,使得该线程停止执行当前工作且可以被中断

    • 进一步,可以使用ThreadPoolExecutor中的newTaskFor方法返回一个定制的FutureTask,封装非标准的取消操作

停止基于线程的服务
  • PrintWriter字符流类是线程安全的

  • 将关闭线程的工作委托给ExecutorService(shutdown和awaitTermination)

  • 还可以使用毒丸对象:必须要生产者消费者数量已知,而且要在无界队列中,毒丸对象才能可靠工作

  • shutdownNow的局限性:在任务执行最后一条指令和线程池将任务记录为“结束”的两个时刻之间,线程池可能被关闭,所以可能任务执行完了却被标记为取消

非正常的任务终止
  • 如果任务抛出了一个未检查异常,那么它能使线程终结,但会首先通知框架该线程已经终结;

  • 可以通过try/catch捕获;Thread API中还提供了UncaughtExceptionHandler,能检测出某个线程由于未捕获的异常而终结的情况。

  • 只有通过execute提交的任务,才能将它抛出的异常交给未捕获异常处理器,而通过submit提交的任务,无论是抛出的未检查异常还是已检查异常,都将被认为是返回状态的一部分。如果由submit提交的任务由于抛出了异常而结束,这个异常会被Future.get封装在ExecutionException中重新抛出

JVM关闭
  • 可以通过调用Runtime.halt或者在操作系统中“杀死”JVM进程,强行关闭JVM

  • 关闭钩子

    • 通过Runtime.addShutdownHook注册的但尚未开始的线程;

    • 正常关闭中,JVM首先调用所有已注册的关闭钩子,所有关闭钩子执行结束,如果runFinalizersOnExit为true,JVM将运行终结器,再停止;

    • 当被强行关闭时,只会关闭JVM,不会运行关闭钩子

  • 守护线程:执行辅助工作,不阻碍JVM的关闭,垃圾回收器

  • 终结器:一些资源(文件句柄或套接字句柄)当不再被需要时,要显式地交还给操作系统。为了实现这个功能,GC对那些定义了finalize方法的对象会进行特殊处理:在GC释放它们后,调用它们的finalize方法,保证一些持久化的资源被释放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值