在java的多线程中有线程组ThreadGroup的概念,ThreadGroup是为了方便线程管理而出现,可以统一设定线程组的一些属性,比如setDaemon,设置未处理异常的处理方法,设置统一的安全策略等等;也可以通过线程组方便的获得线程的一些信息。
每一个ThreadGroup都可以包含一组的子线程和一组子线程组,线程组是以树形的方式存在,通常情况下根线程组是system线程组。system线程组下是main线程组,默认情况下第一级应用自己的线程组是通过main线程组创建出来的。
基本API介绍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| ThreadGroup(String name) ThreadGroup(ThreadGroup parent, String name)
int activeCount() int activeGroupCount() void checkAccess() void destroy() int enumerate(Thread[] list) int enumerate(Thread[] list,boolean recurs) int enumerate(ThreadGroup[] list) int enumerate(ThreadGroup[] list, boolean recurse) String getName() ThreadGroup getParent() void interrupt() boolean isDaemon() boolean isDestroyed() void list() boolean parentOf(ThreadGroup g) void setDaemon(boolean daemon) void setMaxPriority(int pri) int getMaxPriority()
void uncaughtException(Thread t, Throwable e)
|
创建ThreadGroup
简单demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void createThreadGroup() { ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
ThreadGroup group1 = new ThreadGroup("Group1");
System.out.println(currentGroup == group1.getParent());
ThreadGroup group2 = new ThreadGroup(group1, "group2");
System.out.println(group1.parentOf(group2)); }
|
运行结果
结果分析:说明如果没有指定创建ThreadGroup的parent,则默认为当前线程所对应的ThreadGroup,另外需要注意的是,ThreadGroup是树形的分布,这课树的根是system,也就是在类加载时就建立好的,接着在main线程启动时,创建了一个以main为名的ThreadGroup。
使用enumerate获取当前thread
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public static void enumerateThread() throws InterruptedException { ThreadGroup group = new ThreadGroup("group");
Thread thread = new Thread(group, () - { while (true) { try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) { e.printStackTrace(); } } });
thread.start(); TimeUnit.MILLISECONDS.sleep(2);
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
Thread[] list = new Thread[mainGroup.activeCount()];
int recuresize = mainGroup.enumerate(list); System.out.println(recuresize);
recuresize = mainGroup.enumerate(list, false); System.out.println(recuresize); }
|
运行结果:
基本API的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public static void testAPI() throws InterruptedException { ThreadGroup group = new ThreadGroup("group1");
Thread thread = new Thread(group, () - { while (true) { try { TimeUnit.SECONDS.sleep(2); } catch (Exception e) { e.printStackTrace(); } } }); thread.setDaemon(true); thread.start();
TimeUnit.MILLISECONDS.sleep(2); ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup(); System.out.println("activeCount = " + mainThreadGroup.activeCount()); System.out.println("activeGroupCount=" + mainThreadGroup.activeGroupCount()); System.out.println("getMaxPriority = " + mainThreadGroup.getMaxPriority()); System.out.println("getName = " + mainThreadGroup.getName()); System.out.println("getParent = " + mainThreadGroup.getName()); mainThreadGroup.list(); System.out.println("------------------------------------"); System.out.println("parentOf = " + mainThreadGroup.parentOf(group)); System.out.println("parentOf = " + mainThreadGroup.parentOf(mainThreadGroup));
}
|
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12
| activeCount = 2 activeGroupCount=1 getMaxPriority = 10 getName = main getParent = main java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main] java.lang.ThreadGroup[name=group1,maxpri=10] Thread[Thread-0,5,group1] ------------------------------------ parentOf = true parentOf = true
|
最后需要注意的是,group的parent也可以是自己本身,这不知道是不是bug。
setMaxPriority
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public static void threadGroupPriority() { ThreadGroup group = new ThreadGroup("group1");
Thread thread = new Thread(group, () - { while (true) { try { TimeUnit.SECONDS.sleep(2); } catch (Exception e) { e.printStackTrace(); } } }); thread.setDaemon(true); thread.start(); System.out.println("group getMaxPriority()=" + group.getMaxPriority()); System.out.println("thread.getPriority()=" + thread.getPriority());
group.setMaxPriority(3); System.out.println("group getMaxPriority()=" + group.getMaxPriority()); System.out.println("thread.getPriority()=" + thread.getPriority()); }
|
运行结果
1 2 3 4
| group getMaxPriority()=10 thread.getPriority()=5 group getMaxPriority()=3 thread.getPriority()=5
|
在ThreadGroup中线程的优先级是不能大于ThreadGroup设置的最大优先级,但是上面的结果显示线程的优先级大于了ThreadGroup的最大优先级。这是因为,线程在添加时优先级是不大于ThreadGroup的最大优先级,但是后来ThreadGroup修改了最大优先级,但由于线程的优先级已经设置好了,ThreadGroup将不能去更改这个优先级,所以就存在线程组中有大于线程组最大优先级的线程。但是在这之后添加的线程就不会大于线程组的优先级。
ThreadGroup的Damon设置和destory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public static void threadGroupDaemon() throws InterruptedException { ThreadGroup group = new ThreadGroup("group1");
new Thread(group, () - {
try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) { e.printStackTrace(); }
}, "group1-thread").start(); ThreadGroup group2 = new ThreadGroup("group2");
new Thread(group2, () - {
try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) { e.printStackTrace(); }
}, "group2-thread").start();
group2.setDaemon(true); TimeUnit.SECONDS.sleep(3); System.out.println(group.isDestroyed()); System.out.println(group2.isDestroyed()); }
|
运行结果:
当线程组设置为daemon之后,只要线程组中不存在活跃的线程,线程组则自动destory。但是如果线程组没有设置daemon为true,即使线程组中没有活跃的线程,也不会自动destory。
注意一点是:destory只有当线程组和子线程组中没有活跃的线程才能调用,否则抛出异常。