《Java并发编程实战》第七章 取消与关闭 读书笔记

Java没有提供不论什么机制来安全地(抢占式方法)终止线程,尽管Thread.stop和suspend等方法提供了这种机制,可是因为存在着一些严重的缺陷,因此应该避免使用。

但它提供了中断Interruption机制,这是一种协作机制,可以使一个线程终止还有一个线程的当前工作。

一、任务取消

取消操作的原因:

. 用户请求取消

. 有时间限制的操作

. 应用程序事件

. 错误

. 关闭

结束任务的四种方式:

1. run方法运行结束

2. 使用请求关闭标记(比如boolean开关)

3. 使用中断机制

4. 使用Future退出方法

2. 使用请求关闭标记

当运行到并满足条件是使用return退出run方法

变量须要volatile确保变量多线程环境下的可见性。

-样例待填充,没有运行到推断条件就不会退出。所以不是马上退出的办法。

3. 使用中断机制

长处是相对“请求关闭标记”对应更快一些。但也不是马上关闭线程。

void        interrupt()       中断线程。

boolean   interrupted()   測试当前线程是否已经中断。

boolean   isInterrupted() 測试线程是否已经中断。

InterruptedException异常

程序应该对线程中断作出恰当的响应。

//  1
Thread thread = new Thread("interrupt test") {
	public void run() {
		for (;;) {
			doXXX();
			if (Thread.interrupted()) {
				break;
			}
		}
	}
};
thread.start();

// 2
Thread thread = new Thread("interrupt test") {
	public void run() {
		for (;;) {
			try {
				doXXX();
			} catch (InterruptedException e) {
				break;
			} catch (Exception e) {
				// handle Exception
			}
		}
	}
};
thread.start();

//  3
public void foo() throws InterruptedException {
	if (Thread.interrupted()) {
		throw new InterruptedException();
	}
}

4. 使用Future退出方法

boolean cancel(boolean mayInterruptIfRunning)

试图取消对此任务的运行。

boolean isCancelled()

假设在任务正常完毕前将其取消,则返回 true。

*. 处理不可中断的堵塞

*. 採用newTaskFor来封装费标准的取消

二、停止基于线程的服务

之前的任务取消。主要是涉及怎样关闭单个线程而且都是由创建单个线程的对象来进行关闭操作,可是假设线程不是由对象自己而是由线程池统一创建的线程该怎样处理呢?

1. 使用线程的对象进行关闭 - 当前即使不在对象中创建线程而由线程池创建,这个对象依旧能够关闭线程,这点一定要相信程序猿的破坏能力,仅仅是使用第2种方式更符合封装原则。

2. 使用线程池统一管理 - 假设是使用ExecutorService创建就交由其进行关闭操作。

2. 使用线程池统一管理(关闭ExecutorService)

void shutdown()

启动一次顺序关闭。运行曾经提交的任务,但不接受新任务。

假设已经关闭,则调用没有其它作用。

-- 安全关闭方式。

List<Runnable> shutdownNow()

试图停止全部正在运行的活动任务,暂停处理正在等待的任务。并返回等待运行的任务列表。

无法保证可以停止正在处理的活动运行任务。可是会尽力尝试。比如,通过 Thread.interrupt() 来取消典型的实现。所以不论什么任务无法响应中断都可能永远无法终止。

-- shutdownNow方法的局限性,强制关闭方式。

boolean isShutdown()

boolean isShutdown()假设此运行程序已关闭。则返回 true。

3. “毒丸”对象

仅仅有在生产者消费者的数量都已知的情况下,才干够使用“毒丸”对象。

三、处理非正常的线程终止

Thread.UncaughtExceptionHandler全局的捕获的异常处理。通常在应用中用于异常的统计,收集到这些统计后能够相应用进行异常修复。

四、JVM关闭

1. 关闭钩子

Runtime.getRuntime().addShutdownHook(new Thread()) ;

void addShutdownHook(Thread hook)

注冊新的虚拟机来关闭钩子。

2. 守护线程

希望创建一个线程来运行一些辅助工作。但又不希望这个线程阻碍JVM的关闭。能够使用守护线程。

3. 终结器

避免使用终结器finalize

五、參考资料:

"程序应该对线程中断作出恰当的响应" 摘录自《温绍锦 - Java并发程序设计教程》

时间: 2024-10-28 15:07:23

《Java并发编程实战》第七章 取消与关闭 读书笔记的相关文章

《Java并发编程实战》第二章 线程安全性 读书笔记

一.什么是线程安全性 编写线程安全的代码 核心在于要对状态访问操作进行管理. 共享,可变的状态的访问 - 前者表示多个线程访问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与其规范完全一致. 多个线程同时操作共享的变量,造成线程安全性问题. * 编写线程安全性代码的三种方法: 不在线程之间共享该状态变量 将状态变量修改为不可变的变量 在访问状态变量时使用同步 Java同步机制工具: synchronized volatile类型变量 显示锁(Explicit Lock

Java并发编程实战 第16章 Java内存模型

什么是内存模型 JMM(Java内存模型)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将对其他线程可见. JMM为程序中所有的操作定义了一个偏序关系,称为Happens-Before.两个操作缺乏Happens-Before关系,则Jvm会对它们进行任意的重排序. Happends-Before的规则包括: 1. 程序顺序规则.若程序中操作A在操作B之前,则线程中操作A在操作B之前执行. 2. 监视器锁规则.在同一监视器锁上的解锁操作必须在加锁操作之前执行.如图所示,

[Java Concurrency in Practice]第七章 取消与关闭

取消与关闭 要使任务和线程能安全.快速.可靠地停止下来,并不是一件容易的事.Java没有提供任何机制来安全地终止线程(虽然Thread.stop和suspend方法提供了这样的机制,但由于存在缺陷,因此应该避免使用).但它提供了中断,这是一种协作机制,能够使一个线程终止另一个线程的当前工作. 这种协作式的方法是必要的,我们很少希望某个任务.线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态.相反,在编写任务和服务时可以使用一种协作的方式:当需要停止时,它们首先会清除当前正在执

JAVA并发编程实战---第三章:对象的共享(2)

线程封闭 如果仅仅在单线程内访问数据,就不需要同步,这种技术被称为线程封闭,它是实现线程安全性的最简单的方式之一.当某个对象封闭在一个线程中时,这种方法将自动实现线程安全性,即使被封闭的对象本生不是线程安全的. 实现好的并发是一件困难的事情,所以很多时候我们都想躲避并发.避免并发最简单的方法就是线程封闭.什么是线程封闭呢? 就是把对象封装到一个线程里,只有这一个线程能看到此对象.那么这个对象就算不是线程安全的也不会出现任何安全问题.实现线程封闭有哪些方法呢? 1:ad-hoc线程封闭 这是完全靠

Java并发编程实战 第15章 原子变量和非阻塞同步机制

非阻塞的同步机制 简单的说,那就是又要实现同步,又不使用锁. 与基于锁的方案相比,非阻塞算法的实现要麻烦的多,但是它的可伸缩性和活跃性上拥有巨大的优势. 实现非阻塞算法的常见方法就是使用volatile语义和原子变量. 硬件对并发的支持 原子变量的产生主要是处理器的支持,最重要的是大多数处理器架构都支持的CAS(比较并交换)指令. 模拟实现AtomicInteger的++操作 首先我们模拟处理器的CAS语法,之所以说模拟,是因为CAS在处理器中是原子操作直接支持的.不需要加锁. public s

《Java并发编程实战》第九章 图形用户界面应用程序界面 读书笔记

一.为什么GUI是单线程化 传统的GUI应用程序通常都是单线程的. 1. 在代码的各个位置都须要调用poll方法来获得输入事件(这样的方式将给代码带来极大的混乱) 2. 通过一个"主事件循环(Main Event Loop)"来间接地运行应用程序的全部代码. 假设在主事件循环中调用的代码须要非常长时间才干运行完毕,那么用户界面就会"冻结",直到代码运行完毕.这是由于仅仅有当运行控制权返回到主事件循环后,才干处理兴许的用户界面事件. 非常多尝试多线程的GUI框架的努力

JAVA并发编程实战---第三章:对象的共享

在没有同步的情况下,编译器.处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整.在缺乏足够同步的多线程程序中,要对内存操作的执行顺序进行判断几乎无法得到正确的结果. 非原子的64位操作 当线程在没有同步的情况下读取变量时,可能会读到一个失效值,但至少这个值是由之前的某个线程设置,而不是一个随机值.这种安全性保证也被称为最低安全性. Java内存模型要求:变量的读取操作和写入操作都必须是原子操作,但对于非Volatile类型的long和Double变量,JVM允许将64的读操作或写操作

java并发编程实战-第2章-线程安全性

2. 线程安全性 2.1 什么是线程安全性 线程安全类:当一个类被多个线程访问时,不管运行环境中如何调度,这些线程如何交替执行,并且在调用的代码部分不需要额为的同步或者协同.这个类为线程安全类 Thread-safe classes encapsulate any needed synchronization so that clients need not provide their own. 2.1.1. Example: A Stateless Servlet Stateless obje

《Java并发编程实战》第十六章 Java内存模型 读书笔记

Java内存模型是保障多线程安全的根基,这里仅仅是认识型的理解总结并未深入研究. 一.什么是内存模型,为什么需要它 Java内存模型(Java Memory Model)并发相关的安全发布,同步策略的规范.一致性等都来自于JMM. 1 平台的内存模型 在架构定义的内存模型中将告诉应用程序可以从内存系统中获得怎样的保证,此外还定义了一些特殊的指令(称为内存栅栏或栅栏),当需要共享数据时,这些指令就能实现额外的存储协调保证. JVM通过在适当的位置上插入内存栅栏来屏蔽在JVM与底层平台内存模型之间的