取消与关闭

外部代码可以在某个操作正常完成之前,提前使其置入“完成”状态,这个操作就是可取消的

取消的原因,比如,限时操作,用户取消,发生错误,关闭服务等

每一个可取消的task都应该有取消策略,包括怎么取消,任务在何时检查是否取消了,取消时需要做什么操作。

通过volatile标志取消,如果任务中有阻塞操作,则很可能会导致无法检查取消标志,导致无法结束。

通过中断取消,isInterrupted()判断线程的取消状态,Thread的静态方法interrupted,会清除中断状态,并且返回当前的值,而实例方法interrupt则是中断目标线程,只是发出一个请求,不会马上停止。阻塞方法都会检查中断状态,包括sleep,wait,join,检查到中断状态会抛出interruptedException。静态的interrupted方法需要主要,如果不是要屏蔽中断,需要主动抛出interruptedexception或者再次调用interrupt来恢复中断状态。如果任务能够响应中断,通过中断来取消更好。

响应中断,线程都应该有中断策略,一般地中断策略,是线程级或服务级的取消操作:尽快退出,在必要时清理,通知所有者线程已退出。也可以其他中断策略,例如暂停或者重新开始服务,这样的线程和线程池只能用于只能这些策略的任务中。

中断线程

任务和线程对中断的不同响应。一个中断请求可以有一个或多个接收者,中断一个工作者线程,同时意味着取消当前任务和关闭线程。任务不会在自己拥有的线程中执行,通常是在某个服务中执行,非线程所有者不应该调用中断,响应中断两种方法一个直接抛出中断异常,一个是补获后在恢复中断,这种一般用于需要执行其他操作或者因为run方法不能抛checkedexception.执行任务的代码和调用取消的代码都不应该假设线程中断策略,只有线程所有者代码应该封装中断策略,调用中断方法,屏蔽中断异常
通过join和future来做定时取消
不可中断的阻塞
即一些不会响应interrupted异常的阻塞方法
Socket io 中read和write,如果close底层socket,调用读写的线程抛出socket异常
中断一个在interruptiblechannel上等待的线程时,抛出closedinterruptexception,当关闭时,所有在链路上等待的线程都会抛出asynchronouscloseexception
Selector的select方法,调用close或者wakeup,抛出closeselectorexception
内置锁无法响应中断,通过显示的lockinterrupibly可响应中断

通过继承thread,改写interrupt方法或者通过改写executor的newtaskfor来封装非标准取消 应用程序通常会创建拥有多个线程的服务,服务的生命周期比创建它们的方法更长,线程的所有权不可传递,所以应用程序不能直接操作线程,应该由服务来提供关闭方法。关闭生产者消费者时方法一,只使用中断,可能导致生产者线程阻塞,也有可能任务不响应中断,只使用状态变量,有可能被阻塞而不会检查到状态变量,同时使用并且加上计数器,使提交的任务都可以执行完 关闭executorservice,简单程序直接在main中启动和执行,复杂程序可以在包装,所有权链上每一环都提供自己的生命周期管理 关闭生产者消费者方法二,毒丸对象,必须知道生产者和消费者数量,毒丸数量生产者乘以消费者,数量大时难以使用,并且无界队列才能确保安全 在方法内创建executorservice,j简化生命周期管理 Shutdown会等待所有任务执行完毕,而shutdownnow会取消正在执行的任务,但是返回值只包括未开始的任务,可以扩展executorservice记录下取消的任务,任务必须记录中断状态 非正常线程终止,通过 finally在线程终结通知框架,框架可以用新的线程替代,处理糟糕的任务,另一种是uncatchexceptionhandler,通过 threadfactory为线程池设置handler标准线程池会吃掉异常,如果是调用execute方法,handler有用,而submit,会在结果里抛出,可以使用afterexecute或者在任务中捕获异常 Jvm钩子,正常关闭时会调用,包括最后一个非守护结束,system.exit0,平台信号。强制杀死不会掉。关闭进程和其他线程一起执行,执行完钩子,执行终结器,当jvm结束后,其他线程强制结束,如果钩子和执行器未完成,关闭进程被挂起,jvm必须强制关闭,不执行钩子。钩子要线程安全,最好只一个钩子,顺序执行 守护线程关闭时可能无法执行清理工作,所以一般不用,finally可能不执行 终结器不如finally,除了调用现有的类的,如io包中的,一般不用

你可能感兴趣的:(取消与关闭)