• 结构化并发程序——取消与关闭


    一 任务取消

    • 中断——任务的取消策略

      一些特殊的阻塞库的方法支持中断。线程的中断时一种写作机制,通过这种协作机制,线程可以通知另一个的线程,在合适的或者可能的情况下,停止当前工作并且转而执行其他的工作。

         

      在java的API文档中,并没有将中断与任何任务取消的语义关联起来,但是实际上如果在取消之外的其他语义上使用中断,都是不合适的,并且很难支撑起更大的应用。

         

      每个线程都有一个中断状态,当中断目标线程时,目标线程的中断状态将被设置为true。在Thread类中包含了中断线程以及查询线程中断状态的方法。interrupt能中断线程,而isInterrupted能放回目标线程的中断状态,静态的interruptted()方法,将清除当前线程的中断状态,并返回她之前的值,这也是清除线程状态的唯一方法。

      对于阻塞的库方法,例如Thread.seep()和Object.wait()等,都会检查线程的中断状态,发现中断的时候及时返回。它们在相应中断时执行的操作包括:清除中断状态,抛出InterruptedException,表示阻塞操作由于中断提前结束。JVM并不能保证阻塞方法检测到中断的速度,但实际情况响应速度还是非常快的。

         

      (1)调用interrupt并不是意味着立马停止线程正在进行的工作,而是传递了请求中断的消息,然后又线程在下一个合适的时刻中断自己。

      (2)调用interruptted需要特别小心,因为它会清除当前的中断状态。如果调用interruptted返回true,那么除非你想屏蔽这个中断,否则的话应该再次调用interrupt来恢复中断状态。

         

      通常中断是实现取消的最合理方式。

         

    • 中断策略

      正如任务应该有合理的取消策略一样,线程也应该有合理的中断策略。中断策略规定了线程该如何相应某个中断请求——当发生中断时,应该做哪些工作,哪些工作单元对于中断来说是原子操作,以及以多快的速度来相应中断。

         

      对于非线程所有者的代码来说,(例如对于线程池而言,任何在线程池以外实现的代码),应该小心的保存中断的状态,这样拥有线程的代码才能对中断做出相应。这就是为什么大多数克阻塞的库函数只是抛出InterruptedException作为中断响应,因为他们实现了最合理的中断策略:尽快退出执行流程,并把中断信息传递给调用者,从而使调用栈中的上层代码可以采取进一步操作。

      任务不应该对执行该任务的线程的中断策略做出任何猜测,也就是说任务不应该随便的去中断执行任务的线程,而是应该选择把线程的状态进行保存。如果除了将InterruptedException传递给调用者之外,还有其他的操作,那么应该在捕获InterruptedException之后恢复线程的中断状态:

      Thread.currentThread.interrupt().

         

         

    • 响应中断

      在任务中调用可中断的阻塞方法时候,如果在阻塞的时候发生了当前线程被中断,此时底层可中断的阻塞方法会做一下两件事:提前返回并且抛出InterruptException;之后重置线程的中断状态(线程的中断状态又会被置回false)。因此在此时如果任务调用的时候出现这种情况,任务需要将线程的中断情况向上层调用者抛出,由调用者(可能是任务所在的线程)来采取相应的中断策略。因此正确的响应中断的方法就是底层的任务一定在调用可中断的阻塞方法发生中断的时候,一定不能把InterruptException异常私自吞掉对上层调用者隐藏线程的中断状态,而是一定要把中断异常抛给上层调用者。响应中断的方法如下:

      (1)传递异常,从而使你方法也成为可中断的阻塞方法。

      (2)对于那些没法继续把异常继续向上抛出的方法,例如Runnable的run方法,必须对异常进行try-catch处理。此时由于低层可中断的阻塞方法已经将发生中断线程的中断状态重新置为false,这样就相当于任务代码私自处理可中断的事情,而没有上报。这样上层执行任务的线程就不能正确的获知线程的中断状态。因此我们要在任务重处理完异常之后,再次调用Thread.currentThread.interrupt()恢复线程的中断状态。

         

         

    • 通过Futrue实现取消

      Futrue拥有一个取消任务的的方法cancel()。因此我们可以通过ExecutorService.submit()来返回一个Future来描述任务。从而利用Future的cancel()方法实现任务的取消。

       

    • 处理不可中断的阻塞

         

  • 相关阅读:
    SVM+HOG特征训练分类器
    数字图像处理的基本原理和常用方法
    c++中二进制和整数转化
    目标检测——HOG特征
    相似图片搜索的原理和实现——颜色分布法
    测试文本文件大小
    Direct2D 图形计算
    Direct2D 如何关闭抗锯齿
    MFC窗口显隐
    CISP/CISA 每日一题 22
  • 原文地址:https://www.cnblogs.com/JackDesperado/p/4780055.html
Copyright © 2020-2023  润新知