Java线程详解 线程中断 线程局部变量 定时器详解 TimeUnit使用说明 虚拟机关闭钩子

2017-02-26 11:47:00
admin
原创 1452
摘要:Java线程详解 线程中断 线程局部变量 定时器详解 TimeUnit使用说明 虚拟机关闭钩子

一、Java线程详解

硬件环境:

CPU内核数,Runtime.availableProcessors()


线程休眠:

1、休眠指定时间,Thread.sleep;

2、线程永久休眠,Thread.currentThread().join;


daemon线程作用:

1、线程分用户线程User Thread和守护线程Daemon Thread;

2、用户线程一旦结束,守护线程即使没有执行完,JVM也会退出;

3、守护线程一般服务于用户线程或其它守护线程;

4、守护线程必须在线程启动之前设置;


二、线程中断

中断意义和用法:

1、中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断;

2、中断某些阻塞操作时抛出异常,是为了让线程从阻塞醒过来,有机会处理中断;

3、中断用法:设置状态变量,然后调用interrupt,最后线程根据状态处理中断;


中断测试:

1、isInterrupted,测试线程是否被中断,不改变线程的中断状态;

2、interrupted,测试线程是否被中断,且清除线程的中断标志;


中断调用:

1、线程没有启动,调用interrupt无效,isInterrupted返回false;

2、无法中断因获取synchronized锁而等待的线程;

3、中断sleep、wait、join,会导致中断标志位清除且抛出异常InterruptedException,所以catch里面isInterrupted返回false;

4、中断可中断的IO操作,IO通道被关闭,中断标志位置位,同时抛出异常ClosedByInterruptException;

5、中断Selector阻塞,中断标志位置位,同时线程立即从选择操作返回且返回一个非零值;

6、以上情况都不满足,则中断标志位直接置位;


三、线程局部变量

1、ThreadLocal实例通常是类的静态字段,TL实例只有一个,TL代理的变量每个线程一个;

2、线程局部变量存储在每个线程的threadLocals字段,它是一个字典,key是TL实例,value是TL代理的变量;

3、第一次get会调用initialValue,如果之前已经set就不会调用initialValue,initialValue同步语义需要自己实现;

4、只有获取变量初始值需要关注是否需要锁,创建线程局部变量字典和插入变量都是在线程内完成,不需要关注锁;

5、线程独立变量可以用线程局部变量实现,或者自己定义类实现,但线程局部变量更简单;

6、线程销毁会销毁线程局部变量字典,TL代理的变量都会销毁,或者调用TL实例的remove提前销毁;

7、线程局部变量字典的key是弱引用,只有弱引用的对象也会被垃圾回收;

8、代码示例:ThreadLocalDemo.java


四、定时器详解

TimerTask:实例包含一个锁对象,除run以外的方法使用锁对象保证线程安全;

TimerTask.run():执行任务;

TimerTask.cancel():取消任务,如果任务还在队列,并且状态是SCHEDULED,则返回true;

TimerTask.scheduledExecutionTime():返回任务当前的调度时间,用于在run内部和系统当前时间对比;


Timer:实例包含一个锁对象,只有任务执行时不会锁定,其余操作都会锁定;

schedule(TimerTask task, long delay):指定延时执行,等于0立即执行;

schedule(TimerTask task, Date time):指定时间执行,小于等于当前时间则立即执行;

schedule(TimerTask task, Date firstTime, long period):周期性执行,单个任务执行时间太长影响任务执行频率;

scheduleAtFixedRate(TimerTask task, Date firstTime, long period):周期性执行,任务执行频率固定不变;

cancel():取消定时器,可重复执行,不影响正在执行的任务;

purge():移除已经取消的任务,即使不调用此方法,取消的任务下次被调度时也会移除;


1、定时器任务executionTime<=currentTime调度时间小于等于当前时间,则任务开始执行;

2、周期任务不带AtFixedRate,下次任务执行时间executionTime=currentTime+task.period,执行间隔固定;

3、周期任务带AtFixedRate,下次任务执行时间executionTime=executionTime+task.period,执行频率固定;

4、每个定时器包含一个线程、一个任务队列,执行任务抛出异常会导致定时器线程终止;

5、定时器使用sleep机制,sleep的时候持有锁对象,只有执行任务的时候不持有锁对象;

6、定时器使用二叉堆做为调度算法的基础数据结构,O(1)时间取到最快要执行的任务;


五、TimeUnit使用说明

TimeUnit枚举表示时间单元,提供时间转换和延迟操作的实用工具方法:

DAYS
HOURS
MINUTES
SECONDS
MILLISECONDS
MICROSECONDS
NANOSECONDS


时间转换:

convert(long sourceDuration, TimeUnit sourceUnit),将原时间片段转化为当前时间片段
toMinutes(long duration),等价于MINUTES.convert(duration, this)
toSeconds(long duration),等价于SECONDS.convert(duration, this)


时间转换示例:

System.out.println(TimeUnit.MINUTES.toSeconds(1)),1分钟等于60秒

System.out.println(TimeUnit.DAYS.toSeconds(1)),1天等于86400秒


延迟操作:
sleep(long timeout),调用Thread.sleep

timedJoin(Thread thread, long timeout),调用Thread.join

timedWait(Object obj, long timeout),调用Object.wait


六、虚拟机关闭钩子

1、Runtime.addShutdownHook注册钩子,Runtime.removeShutdownHook清除钩子;

2、钩子执行场景:程序正常退出,调用System.exit或者Runtime.exit,kill -15(kill -9不能),操作系统关机;

3、可以注册多个钩子,在虚拟机注销时多个钩子同时执行,执行顺序具备不确定性;

4、钩子执行时,如果还有守护或者非守护线程在运行,则这些线程将继续运行;

5、用户注销或者关机时,操作系统可能只允许进程在固定时间内退出,所以在钩子里面不能执行耗时操作;


发表评论
评论通过审核之后才会显示。