《Java多线程编程核心技术》读书笔记
第五章 定时器Timer
写在前面,现在基本上很少使用JDK自带的Timer和TimerTask,因为各种问题:
- 时间计算不准确:timer是以绝对时间计算定时任务的,因此会受到系统时间的影响。
- 单次只能执行一次任务:每次只从队列中拿出一个任务执行。
- 前面的任务出现错误的话后面的任务不会执行。
同一个TimerTask对象不能够被schedule两次,否则会抛出TimerTask is scheduled already。
当一个TimerTask被cancel的时候需要重新进行实例化才可以schedule,否则会抛出出TimerTask is canceled。
一般用quartz或者concurrent包下面的ScheduledThreadPoolExecutor或者spring的ThreadPoolTaskExecutor来代替。故本章节的内容大致看看即可,无需深究。
TimerTask 以列队的形式一个个被顺序执行,故而后面的任务的运行时间会被延迟;
TimerTask 类的cancel方法将自身从任务队列中移除,其他任务不受影响;
Timer 类的cancel方法是将任务队列的全部任务清空;但是这个cancel方法有时不一定会停止执行计划任务,而是正常执行;
方法 schedule 和 scheduleAtFixedRate 的主要区别在于不延迟的情况:
schedule:如果执行任务的时间没有被延迟,则下一次任务的执行时间参考上一次任务的开始时间来计算;schedule方法不具有追赶执行性
scheduleAtFixedRate:如果执行任务的时间没有被延迟,则下一次任务的执行时间参考的上一次任务的结束时间来计算;scheduleAtFixedRate 方法具有追赶执行性;
第六章 单例模式与多线程
立即加载,饿汉模式,在调用方法之前,实例已经被创建;
延迟加载,懒汉模式,在调用get()方法时,实例才被创建,在get方法里面进行new实例化,多线程环境下会出现多个实例的情况;仅仅使用synchronized语句块,不能解决问题;需要使用DCL双重检查锁的机制;
另外,还可以使用静态内部类的方式来实现单例模式;但是,遇到序列化对象时,单例模式会被破坏,此时需要重写**readResolve()**方法,返回创建的单例;
静态代码块中的代码在使用类时已经执行,也可以用来实现单例模式:
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
static {
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
最后就是使用枚举类来实现单例模式;
第七章 拾遗增补
方法与状态关系示意图:
NEW:线程实例化之后还没有执行过start方法时的状态;
RUNNABLE:线程进入运行的状态;
TERMINATED:线程被销毁的状态;
TIMED_WAITING:线程执行Thread.sleep()方法,等待状态;
BLOCKED:某一个线程在等待锁的时候;
WAITING:线程执行Object.wait()方法之后所处的状态;
线程组
线程对象关联线程组:1级关联;
线程对象关联线程组:多级关联,不推荐,结构设计复杂反而不利于线程对象的管理;
自动归属就是自动归档到当前线程组;
获取根线程组:Thread.currentThread().getThreadGroup().getParent().getName(),JVM的根线程组就是system,再取其父线程组则抛NPE。
线程组内的线程批量停止:调用线程组ThreadGroup的interrupt()方法,将组内的所有正在运行的线程批量停止。
递归以及非递归取得组内对象:ThreadGroup.enumerate()方法,入参true表示递归。
线程有序性:改造代码的方式才能实现;
SimpleDataFormat非线程安全,解决方法1:创建多个实例;2. 使用ThreadLocal将线程绑定到指定的对象上去。
使用UncaughtExceptionHandler对发生的异常进行有效的处理,其setDefaultUncaughtExceptionHandler()方法对指定的线程对象设置默认的异常处理器,setUncaughtExceptionHandler自定义;默认情况下,线程组内的一个线程出现异常不会影响其他线程的执行;使用自定义java.lang.ThreadGroup线程组,重写uncaughtException方法处理组内线程中断行为时,每个线程对象中的run()方法内部不要catch异常,否则重写的uncaughtException方法不执行。线程异常处理的传递。