目录
线程组概念理解
在java的多线程处理中有线程组threadgroup的概念,threadgroup是为了方便线程管理出现了,可以统一设定线程组的一些属性,比如setdaemon,设置未处理异常的处理方法,设置统一的安全策略等等;也可以通过线程组方便的获得线程的一些信息。
每一个threadgroup都可以包含一组的子线程和一组子线程组,在一个进程中线程组是以树形的方式存在,通常情况下根线程组是system线程组。system线程组下是main线程组,默认情况下第一级应用自己的线程组是通过main线程组创建出来的。
我们可以通过下面代码片段看下一个简单的java application中线程组的情况:
package cn.outofmemory.concurrent; public class threadgroupdemo { public static void main(string[] args) { printgroupinfo(thread.currentthread()); thread appthread = new thread(new runnable(){ @override public void run() { for (int i=0;i<5;i ) { system.out.println("do loop " i); } } }); appthread.setname("appthread"); appthread.start(); printgroupinfo(appthread); } static void printgroupinfo(thread t) { threadgroup group = t.getthreadgroup(); system.out.println("thread " t.getname() " group name is " group.getname() " max priority is " group.getmaxpriority() " thread count is " group.activecount()); threadgroup parent=group; do { threadgroup current = parent; parent = parent.getparent(); if (parent == null) { break; } system.out.println(current.getname() "'s parent is " parent.getname()); } while (true); system.out.println("--------------------------"); } }
这段代码打印结果如下:
thread main group name is main max priority is 10 thread count is 1 main's parent is system -------------------------- thread appthread group name is main max priority is 10 thread count is 2 main's parent is system -------------------------- do loop 0 do loop 1 do loop 2 do loop 3 do loop 4
在创建线程时可以通过构造函数指定其所在的线程组,如下代码:
threadgroup group=new threadgroup("worker"); thread thread=new thread(group,"the first thread of group");
通常情况下我们创建线程时可能不设置线程组,这时候创建的线程会和创建该线程的线程在一个组里面。
线程组实践
下面通过实例演示如何使用threadgroup,该实例中设定了线程组的daemon属性,设置了线程组内线程的最大优先级,通过继承threadgroup的方式,重写了该线程组对于未处理异常的处理逻辑。
请看下面代码:
package cn.outofmemory.concurrent; import java.net.socketexception; public class threadgroupdemo2 { public static void main(string[] args) { threadgroup spidergroup = new spiderthreadgroup("spidergroup"); //可以统一设定线程是否为守护线程 spidergroup.setdaemon(true); //可以设置线程组内的最大优先级 spidergroup.setmaxpriority(thread.norm_priority); //初始化线程 thread spiderthread = new thread(spidergroup, new runnable() { @override public void run() { throw new runtimeexception(new socketexception()); } }); //启动线程 spiderthread.start(); } /** * 此类从threadgroup类继承重写了其uncaughtexception方法,对于socketexception进行了特殊处理 * @author outofmemory.cn * */ static class spiderthreadgroup extends threadgroup { public spiderthreadgroup(string name) { super(name); } public void uncaughtexception(thread t, throwable e) { if (e.getcause() instanceof socketexception) { system.out.println("socket exception should be process"); } else { super.uncaughtexception(t, e); } } } }
上面的实例代码会输出如下内容:
socket exception should be process
说明未处理异常已经被统一处理了。
下面我们通过另外一个示例演示如何通过线程组,方便的获得应用中一共有多少个活动线程,并打印这些活动线程的名字。
package cn.outofmemory.concurrent; public class threaddemo3 { public static void main(string[] args) { threadgroup g = thread.currentthread().getthreadgroup(); while (g != null) { threadgroup temp = g.getparent(); if (temp == null) { break; } g = temp; } //现在g就是跟线程组 system.out.println("active count is " g.activecount()); thread[] all = new thread[g.activecount()]; g.enumerate(all); for (thread t : all) { system.out.println(t.getname()); } } }
你不妨猜猜这个小程序的输出结果,按理说我只有一个main方法,没有任何自定义线程,那么会输出几个线程呢?
下面是输出结果:
active count is 5 reference handler finalizer signal dispatcher attach listener main
一共有5个线程,这5个线程除了main是我们自己代码run所在的线程,其他都是虚拟机启动的线程。是不是出乎你的意外了?
线程组和线程池的区别
线程组和线程池是两个不同的概念,他们的作用完全不同,线程组是为了方便线程的管理,线程池是为了管理线程的生命周期,复用线程,减少创建销毁线程的开销。
在构建线程池时,threadpoolexcutor的构造方法中,生成线程工厂的参数threadfactory接口的实现类defaultthreadfactory中有个属性,threadgroup
public threadpoolexecutor(int corepoolsize, int maximumpoolsize, long keepalivetime, timeunit unit, blockingqueueworkqueue, threadfactory threadfactory, rejectedexecutionhandler handler) { if (corepoolsize < 0 || maximumpoolsize <= 0 || maximumpoolsize < corepoolsize || keepalivetime < 0) throw new illegalargumentexception(); if (workqueue == null || threadfactory == null || handler == null) throw new nullpointerexception(); this.corepoolsize = corepoolsize; this.maximumpoolsize = maximumpoolsize; this.workqueue = workqueue; this.keepalivetime = unit.tonanos(keepalivetime); this.threadfactory = threadfactory; this.handler = handler; }
public class defaultthreadfactory implements threadfactory { private static final atomicinteger poolid = new atomicinteger(); private final atomicinteger nextid = new atomicinteger(); private final string prefix; private final boolean daemon; private final int priority; protected final threadgroup threadgroup; ...... }