线程组
线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。
构造函数
ThreadGroup(String name)//默认parent为当前线程组
ThreadGroup(ThreadGroup parent, String name)
具体方法
//评估当前活跃的线程数,包括当前group和子group
//不准确因为有可能刚好有新线程加入或销毁
activeCount()
//返回当前活跃的子线程组
activeGroupCount()
//用于销毁线程组及其所有子组。 线程组必须为空,表示线程组中的所有线程都已停止,否则会抛出异常
//它不能作为线程退出的方法
destroy()
//复制当前线程组包括子组的线程到数组中,如果recurse=false,则不复制子组
enumerate(Thread[] list)
enumerate(Thread[] list, boolean recurse)
//返回当前线程组名字
getName()
//获得父线程组
getParent()
//打断所有线程
interrupt()
//等所有线程运行完成后会自动销毁,不需要手动调用destroy()
setDaemon(boolean daemon)
//标志位判断函数
isDaemon()
isDestroyed()
parentOf(ThreadGroup g)
作用
- 通过ThreadGroup的
activeCount
获取当前活跃的线程 - 通过ThreadGroup的
interrupt
方法中断所有的线程
public class ThreadGroupDemo2 {
static class SleepTask implements Runnable {
@Override
public void run() {
try {
TimeUnit.HOURS.sleep(1);// 休眠1小时
} catch (InterruptedException e) {
//ignore
}
}
}
public static void main(String[] args) {
ThreadGroup threadGroup = new ThreadGroup("group");
Thread thread1 = new Thread(threadGroup, new SleepTask(), "thread1");
Thread thread2 = new Thread(threadGroup, new SleepTask(), "thread2");
//activeCount方法用于返回当前活跃的线程,因为刚创建时2个线程都没有启动因此返回0
assert threadGroup.activeCount() == 0;
thread1.start();
thread2.start();
//线程组中的2个线程都启动了,active为2
assert threadGroup.activeCount() == 2;
threadGroup.interrupt();
//中断之后,active为0
assert threadGroup.activeCount() == 0;
}
}
线程池
线程的创建和销毁需要消耗资源,所以通过线程池,用完的线程可以及时回收供其他程序使用,节约了创建和销毁的浪费。
课程里面这一部分并没有介绍并发包中的线程池知识,第三部分才会教,这里是手写线程池。
线程池的初始化
- 初始化一定数量线程,进入阻塞状态,等待任务。通过线程队列管理
- 启动线程池自身监控线程
任务调度
- 任务放入任务队列,并通知线程开始取任务工作
- 任务队列的放入和取出需要加锁
拒绝策略
- 当任务队列过长时,可以做出选择,抛出异常,直接丢弃,阻塞,临时队列
闲时回收和忙时扩增
- init--初始大小,active--活跃大小,max--最大线程数
- 通过启动线程池的一个监控程序,实时对线程队列进行扩增或缩小
线程关闭
- run状态下,通过标志位改变使线程结束
- block状态下,通过interrupt让线程捕获异常使线程结束