天天看点

《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表示递归。

线程有序性:改造代码的方式才能实现;

继续阅读