阅读《Java高并发编程详解》后的笔记。
ThreadGroup
Java中,默认情况下,新的线程都会加入到main线程所在的group中,main线程的group名字同线程名。和线程存在父子关系一样,ThreadGroup也存在父子关系。
复制Thread和ThreadGroup
- public int enumerate(Thread[] list)
- public int enumerate(Thread[] list,boolean recurse)
将ThreadGroup中active线程全部复制大Thread数组中,recurse为true,将所有子group中active线程递归到Thread数组中。
- public int enumerate(ThreadGroup[] list)
- public int enumerate(ThreadGroup[] list,boolean recurse)
ThreadGroup的复制与复制Thread数组类似。
基本API
- activeCount():获取group中活跃线程,是个估计值。
- activeGroupCount():获取group中活跃的子group。
- list():将group中所有活跃线程的信息全部输出。
ThreadGroup的interrupt
interrupt一个thread group会导致group中所有active线程都被interrupt。
ThreadGroup的destroy
该方法只针对任何一个没有active线程的group进行一次destroy标记,调用结果是在父group中将自己移除。
守护ThreadGroup
将一个ThreadGroup设置为deamon,deamon被设置为true,group中没有任何active线程的时候该group自动deatroy,不会影响线程的deamon属性。
守护线程
简介:守护线程一般用于处理一些后台的工作,如JDK的垃圾回收线程。
设置:若要设置守护线程,调用setDeamon(boolean bool) ,true代表守护线程,false是正常线程。该方法只在线程启动之前有效,如果一个县城已经死亡,那么再设置会抛出IllegalThreadException。
作用:如果一个JVM进程中没有一个非守护线程(就是说有一个守护线程),那么JVM会自动退出。所以守护线程具备自动结束生命周期的特性,而非守护线程不具备。比如一个简单的游戏程序,其中一个线程与服务器不断交互获取玩家最新的金币等信息,希望退出时这些数据同步的工作也能立刻结束,这就可以使用守护线程完成需求。
Hook线程
JVM进程退出是由于JVM中没有活跃的非守护线程,或者受到了系统中断信号,向JVM程序注入Hook线程,在JVM进程退出的时候,Hook进程会启动执行。通过Runtime可为JVM注入多个Hook线程。
Runtime.getRuntime().addShutdownHook();
作用:帮助程序获得进程中断信号,有机会在进城退出之前做一些释放资源的工作(如关闭socket连接,数据库connection等)或者告警通知。但如果强制杀死进程,进程将收不到任何中断信号。
注意:尽量不要在Hook线程中执行一些耗时非常长的操作,会导致程序迟迟不能退出。
线程池
线程池原理图:
线程池,里面放着已经创建好的线程,当有任务提交给线程池执行时,某个线程会主动执行该任务,如果线程数量不够应付众多任务时,需要自动扩充新的线程到池子中,但是该数量是有限的,若是池子中的任务比较少的时候,池子中的线程能够自动回收,释放资源。
所以一个完整的线程池应该具备要素:
(1)任务队列:用于缓存提交的任务。
(2)线程数量管理功能:创建线程池的初始数量init,线程池扩充的最大数量max,线程池空闲时需要释放但也维护的活跃数量或者核心数量core,init<=core<=max
(3)任务拒绝策略:线程数量达到上限或者任务队列已满,通知任务提交者。
(4)线程工厂:如设置守护线程或者设置线程名称等。
(5)QueueSize:存放提交的Runnable,limit控制防止内存溢出。
(6)Keepdalive:决定线程各个重要参数自动维护的时间间隔。