第 7 章 拾遗增补

本章主要内容

  1. 线程组的使用。
  2. 如何切换线程状态。
  3. SimpleDataFormat 类与多线程的解决办法。
  4. 如何处理线程的异常。

7.1 线程的状态

  线程对象在不同的运行时期有不同的状态,状态信息就存在于 State 枚举类中,如下图:

  每个枚举类型的解释如下图:

  调用与线程有关的方法是造成线程状态改变的主要原因,其因果关系如下图:

  在调用与线程有关的方法后,会进入不同的次线程状态,这些状态之间某些是可双向切换的,比如 WAITING 和 RUNNING 状态之间可以循环地进行切换;而有些是单向切换的,比如线程销毁后并不能自动进入 RUNNING 状态。

7.1.1 验证 NEW、RUNNABLE 和 TERMINATED

  首先验证的是 NEW、RUNNABLE 及 TERMINATED 状态,NEW 状态是线程实例化后还从未执行 start() 方法时的状态,而 RUNNABLE 状态是线程进入运行的状态,TERMINATED 是线程被销毁时的状态。

7.1.2 验证 TIMED_WAITING

  线程状态 TIMED_WAITING 代表线程执行了 Thread.sleep() 方法,呈等待状态,等待时间到达,继续向下运行。

  执行 sleep() 方法后线程的状态枚举值就是 TIMED_WAITING。

7.1.3 验证 BLOCKED

  BLOCKED 状态出现在一个线程在等待锁的时候。

7.1.4 验证 WAITING

  状态 WAITING 是线程执行了 Object.wait() 方法后所处的状态。

  执行 wait() 方法后线程的状态枚举值就是 WAITING。

7.2 线程组

  可以吧线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程。这样的组织结构有些类似于树的形式。如下图:

  线程组的作用是,可以批量的管理线程或线程组对象,有效地对线程或线程组对象进行组织。

7.2.1 线程对象关联线程组:1 级关联

  所谓的 1 级关联就是父对象中有子对象,但并不创建子孙对象。这种情况经常出现在开发中,比如创建一些线程时,为了有效地对这些线程进行组织管理,通常的情况下是创建一个线程组,然后再将部分线程归属到该组中。这样的处理可以对零散的线程对象进行有效的组织与规划。

7.2.2 线程对象关联线程组:多级关联

  所谓的多级关联就是父对象中有子对象,子对象中再创建子对象,也就是出现子孙对象的效果了。但是此种写法在开发中不太常见,如果线程树结构设计得非常复杂反而不利于线程对象的管理,但 JDK 却提供了支持多级关联的线程树结构。

  线程必须启动然后才可以归到组中。

  线程必须在运行状态才可以受组管理。

7.2.3 线程组自动归属特性

  自动归属就是自动归到当前线程组中。

  方法 activeGroupCount() 取得当前线程组对象中的子线程组数量。

  方法 enumerate() 的作用是将线程组中的子线程组以复制的形式拷贝到 ThreadGroup() 数组对象中。

  在实例化一个 ThreadGroup 线程组 x 时如果不指定所属的线程组,则 x 线程组自动归到当前线程对象所属的线程组中,也就是隐式地在一个线程组中添加了一个子线程组。

7.2.4 获取根线程组

  JVM 的根线程组就是 system,再取其父线程组则出现空异常。

7.2.5 线程组里加线程组

  1. ThreadGroup newGroup = new ThreadGroup(Thread.currentThread().getThreadGroup(),"newGroup");

7.2.6 组内的线程批量停止

  通过将线程归属到线程组中,当调用线程组 ThreadGroup 的 interrupted() 方法时,可以将该组中的所有正在运行的线程批量停止。

7.2.7 递归与非递归取得组内对象

  1. //分配控件,但不一定全部用完
  2. ThreadGroup[] listGroup1 = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
  3. //传入 true 是递归取得子组及子孙组,false是只取子组
  4. Thread.currentThread().getThreadGroup().enumerate(listGroup1,true);

7.3 使线程具有有序性

  正常的情况下,线程在运行时多个线程之间执行任务的时机是无序的。可以通过改造代码的方式使它们运行具有有序性。

  使用 synchronized 同步的方法让线程顺序执行。

7.4 SimpleDateFormat 非线程安全

  类 SimpleDateFormat 主要负责日期的转换与格式化,但在多线程的环境中,使用此类容易造成数据转换及处理的不准确,因为 SimpleDateFormat 类并不是线程安全的。

7.4.1 出现异常

  使用单例的 SimpleDateFormat 类在多线程的环境中处理日期,极易出现日期转换错误的情况。

7.4.2 解决异常方法 1

  解决处理错误的方法就是创建了多个 SimpleDateFormat 类的实例。

7.4.3 解决异常方法 2

  ThreadLocal 类能使线程绑定到指定的对象。使用该类也可以解决多线程环境下 SimpleDateFormat 类处理错误的情况。

  1. private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<SimpleDateFormat>();

7.5 线程中出现异常的处理

  在 Java 的多线程技术中,可以对多线程中的异常进行“捕捉”,使用的是 UncaughtExceptionHandler 类,从而可以对发送的异常进行有效的处理。

  方法 setUncaughtExceptionHandler() 的作用是对指定的线程对象设置默认的异常处理器。

  方法 setUncaughtExceptionHandler() 是给指定线程对象设置的异常处理器。在 Thread 类中还可以使用 setDefaughtExceptionHandler() 方法对所有线程对象设置异常处理器。

  方法 setDefaultUncaughtExceptionHandler() 的作用是为指定线程类的所有线程对象设置默认的异常处理器。

7.6 线程组内处理异常

  在默认的情况下,线程组中的一个线程出现异常不会影响其他线程的运行。

  Thread 的 uncaughtException(Thread t,Throwable e) 方法中的 t 参数是出现异常的线程对象。

  需要注意的是,使用自定义 java.lang.ThreadGroup 线程组,并且重写 uncaughtException 方法处理组内线程中断行为时,每个线程对象中的 run() 方法内部不要有异常 catch 语句,如果有 catch 语句,则 public void uncaughtException(Thread t,Throwable e) 方法不执行。

7.7 线程异常处理的传递

  测试若干个线程异常处理的方式放在一起运行的情况。

  ThreadGroup 覆盖实现 uncaughtException(Thread t,Throwable e) 方法,并且调用 Thread 的 setUncaughtExceptionHandler() 与 setDefaultUncaughtExceptionHandler() 方法设置对象与全局的异常处理类。

  运行一个线程(不设置组),即调用 setUncaughtExceptionHandler() 方法,也调用 setDefaultUncaughtExceptionHandler() 方法出现异常只会回调对象的异常处理(setUncaughtExceptionHandler())。

  运行一个线程(不设置组),不调用 setUncaughtExceptionHandler() 方法,只调用 setDefaultUncaughtExceptionHandler() 方法, 则不会回调任何的异常处理。

  创建一个线程组,将线程加入到线程组中,并且调用 Thread 的 setUncaughtExceptionHandler() 与 setDefaultUncaughtExceptionHandler()方法,线程异常则调用对象的异常处理(setUncaughtExceptionHandler())。

  创建一个线程组,将线程加入到线程组中,只调用 Thread 的 setDefaultUncaughtExceptionHandler()方法,线程异常则调用全局的异常处理(setDefaultUncaughtExceptionHandler())。

  创建一个线程组,将线程加入到线程组中,不调用 Thread 的 setUncaughtExceptionHandler() 与 setDefaultUncaughtExceptionHandler()方法,,线程异常则调用线程组的异常处理(ThreadGroup::uncaughtException(Thread t,Throwable e))。

  如果想要打印“静态的异常处理”的信息,则必须在 public void uncaughtException(Thread t,Throwable e)方法中加上 super.uncaughtException(t,e);代码。

7.8 本章总结

  本章弥补了前面几个章节遗漏的技术空白点。

Java多线程编程核心技术-第7章-拾遗增补-读书笔记的更多相关文章

  1. Java多线程编程核心技术-第5章-定时器 Timer-读书笔记

    第 5 章 定时器 Timer 定时 / 计划功能在移动开发领域使用较多,比如 Android 技术.定时计划任务功能在 Java 中主要使用的就是 Timer 对象,他在内部使用多线程的方式进行处理 ...

  2. Java多线程编程实战指南(核心篇)读书笔记(五)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

  3. Java多线程编程实战指南(核心篇)读书笔记(四)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76690961冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

  4. Java多线程编程实战指南(核心篇)读书笔记(三)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76686044冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

  5. Java多线程编程实战指南(核心篇)读书笔记(二)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76651408冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

  6. Java多线程编程实战指南(核心篇)读书笔记(一)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76422930冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

  7. Java多线程编程核心技术-第1章-Java多线程技能-读书笔记

    第 1 章 Java 多线程技能 本章主要内容 线程的启动 如何使线程暂停 如何使线程停止 线程的优先级 线程安全相关的问题 1.1 进程和多线程的概念及线程的优点 进程是操作系统结构的基础:是一次程 ...

  8. Java多线程编程核心技术-第4章-Lock的使用-读书笔记

    第 4 章 Lock 的使用 本章主要内容 ReentrantLocal 类的使用. ReentrantReadWriteLock 类的使用. 4.1 使用 ReentrantLock 类 在 Jav ...

  9. java多线程编程核心技术——第七章补漏拾遗

    本章主要知识点: 1)线程组的使用 2)如何切换线程状态 3)SimpleDateFormat类与多线程的解决方法 4)如何处理线程异常. 这本书基本来到了终点,其实在第四章来说,核心(基础)的线程知 ...

随机推荐

  1. [LeetCode] 6. ZigZag Conversion 之字型转换字符串

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  2. IDEA中把普通的Java项目转换成gradle项目

    1.在该项目的跟目录下创建build.gradle 和 settings.gradle文件,内容如下: build.gradle: plugins { id 'java' } group 'coco' ...

  3. Idea必知必会

    声明:此文章根据后续用的越来越多,将会不断补充,之所以以链接的形式,是因为不想在这种使用层面上重复造轮子,写很多重复文章,后续我打算写一些更深入的文章. idea常用操作: idea如何Debug调试 ...

  4. js原型和原型链,以及__proto__、prototype属性

    __proto__和prototype属性: 1.__proto__属性: 在JS里,万物皆对象(函数是对象.原型也是对象...).对象都具有属性__proto__,这个属性会指向该对象的原型. 2. ...

  5. Linux下Maven私服Nexus3.x环境构建操作记录

    原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79553747 私服介绍 私服是指私有服务器,是架设在局域网的一种特殊的远程仓库, ...

  6. 微信小程序子组件样式不起作用的解决办法

    今天我在编写微信小程序项目时,发现父组件引用子组件过后,子组件的样式不起作用,在上网查了很多解决办法后,成功解决了这一问题. 解决办法: 1.在全局样式文件app.wxss中引入子组件的样式,如 @i ...

  7. Sitecore 创建并实施自定义营销分类

    在Sitecore体验平台中,分类法是一种组织项目的方式.您可以应用分类标签来识别广告系列,引荐渠道以及有关营销活动的其他信息.这使您可以识别和跟踪各种营销活动之间的关系,从而更深入地了解广告系列的效 ...

  8. SSM基本配置详解

    需要查看SSM基本依赖和完整配置文件的到:SSM基本配置及依赖 示例项目:SSMDemo 1 Spring IOC容器配置 1.1 applicationContext.xml 1.1.1 配置数据源 ...

  9. Java学习:注解简介

    JAVA 注解的基本原理 以前,『XML』是各大框架的青睐者,它以松耦合的方式完成了框架中几乎所有的配置,但是随着项目越来越庞大,『XML』的内容也越来越复杂,维护成本变高. 于是就有人提出来一种标记 ...

  10. dotnet验证参数

    组长提了一个需求,前端传递过来参数的时候,我们要验证一下参数是否都传递过来了,所以我专门写了一个验证工具类,调用就好了. 第一个参数为 前端传递到Controller封装的实体类,第二个参数为这个实体 ...