Java线程详解 线程中断 线程局部变量 定时器详解 虚拟机关闭钩子
- 2017-02-26 11:47:00
- admin
- 原创 1626
一、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,操作系统关机;
3、可以注册多个钩子,在虚拟机注销时多个钩子同时执行,执行顺序具备不确定性;
4、钩子执行时,如果还有守护或非守护线程在运行,则这些线程将继续运行;
5、用户注销或关机时,操作系统只允许进程在固定时间内退出,在钩子里面不能执行耗时操作;