线程一1.0 线程 ThreadGroup
ThreadGroup和Thread 、
在Java程序中,默认,新的线程会被加入main所在的group中,main线程的group名字同线程名,如同线程存在父子关系一样,threadgroup同样也存在父子关系,下图说明了父子thread,父子threadGroup 以及thread和group之间的层次关系:
无论如何线程都会被加入到某个threadgroup中。
二: 创建threadgroup;
语法:public threadgroup(string name)
public threadGroup (ThreadGroup parent, string name)
创建threadGroup非常简单,通过上面构造函数就行,
public static void main(String[] args) {
//获取当前线程的group
ThreadGroup currentGroup=Thread.currentThread().getThreadGroup();
//定义一个新的group
ThreadGroup group1 = new ThreadGroup("Group1");
System.out.println(group1.getParent()==currentGroup);
//定义一个group2,指定group1为其父group
ThreadGroup group2 = new ThreadGroup(group1,"Group2");
System.out.println(group2.getParent()==group2);
}
}
结果:
true
true
三复制thread 和threadgroup 数组
先看如下两个方法:
public int enumerate(Thread [] list)
public int enumerate(Thread [] list ,boolean recurse)
上面两个方法会将threadGroup中的active线程全部复制到thread数组中。其中recurse参数为true的话,则该方法会将所有的子group中的active线程都递归到thread数组中,
测试一下:
public static void main(String[] args) throws InterruptedException {
//定义一个新的group
ThreadGroup myGroup = new ThreadGroup("myThreadGroup");
Thread thread =new Thread(myGroup,()->{
while(true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} ,"myThread");
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
Thread []list = new Thread[mainGroup.activeCount()];
int recurseSize = mainGroup.enumerate(list);
System.out.println(recurseSize);
recurseSize=mainGroup.enumerate(list, false);
System.out.println(recurseSize);
}
}
输出最后一个比第一个少1,因为代码中将recurse设置为了false,myGroup将不会包含在内
复制threadgroup 数组
public interruptenumerate(threadgroup【】 list)
public int enumerate(threadGroup [] list ,boolean recurse)
和复制thread 类似,上面方法主要用于复制当前Threadgroup 的子group, 同样recurse会决定是否以递归的方式复制。
public static void main(String[] args) throws InterruptedException {
//定义一个新的group
ThreadGroup myGroup1 = new ThreadGroup("myGroup1");
ThreadGroup myGroup2 = new ThreadGroup(myGroup1,"myGroup2");
TimeUnit.MILLISECONDS.sleep(2);
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
ThreadGroup [] list=new ThreadGroup[mainGroup.activeCount()];
int recurseSize=mainGroup.enumerate(list);
System.out.println(recurseSize);
recurseSize=mainGroup.enumerate(list, false);
System.out.println(recurseSize);
}
}
上面代码,mygroup1 的父group 为mainGroup,而mygroup2的父group为myGroup1,因此运行后,递归复制结果为2,不递归结果为1
三 threadgroup的interrupt
interrupt 一个threadgroup 会导致该group中所有的active线程都被interrupt,也就是该group的没一个线程的interrupt标识都被设置了,下面是threadgroup的interrupt源码:
interrupt内部会执行所有的thread的interrupt方法,并且会递归获取子group,然后执行他们各自的interrupt方法,测试一下:
public static void main(String[] args) throws InterruptedException {
//定义一个新的group
ThreadGroup myGroup1 = new ThreadGroup("TestGroup");
new Thread(myGroup1,()-> {
while(true) {
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
// TODO: handle exception
break;
}
}
System.out.println("t1 will exit,");
},"t1").start();
new Thread(myGroup1,()-> {
while(true) {
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (Exception e) {
// TODO: handle exception
break;
}
}
System.out.println("t2 will exit,");
},"t2").start();
TimeUnit.MILLISECONDS.sleep(2);
myGroup1.interrupt();
}
}
结果,group中的active thread都将被interrupt
四: threadgroup中的destroy
destroy 用于销毁threadgroup,该方法只是针对一个没有任何active线程的group进行一次destroy 标记,调用改方法的直接结果及时在父group中将自己移除,
测试一下:
public static void main(String[] args) throws InterruptedException {
//定义一个新的group
ThreadGroup myGroup1 = new ThreadGroup("TestGroup");
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
System.out.println("group .isDestroyed="+myGroup1.isDestroyed());
mainGroup.list();
myGroup1.destroy();
System.out.println("group.isdestroyed="+myGroup1.isDestroyed());
mainGroup.list();
}
结果如下:
五,守护threadgroup
线程可以设置为守护线程,threadgroup也可以设置为守护threadgroup,但是若将一个threadgroup设置为daemon,也并不会影响线程的daemon属性,如果一个threadgroup的daemon被设置为true,那么在group中没有任何active线程的时候该group将自动destroy,测试一下:
public class ThreadGroupCreator {
public static void main(String[] args) throws InterruptedException {
//定义一个新的group
ThreadGroup myGroup1 = new ThreadGroup("group1");
new Thread(myGroup1,()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
// TODO: handle exception
}
},"group1-thread").start();
ThreadGroup myGroup2 = new ThreadGroup("group2");
new Thread(myGroup2,()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
// TODO: handle exception
}
},"group2-thread").start();
myGroup2.setDaemon(true);
TimeUnit.SECONDS.sleep(3);
System.out.println(myGroup1.isDestroyed());
System.out.println(myGroup2.isDestroyed());
}
}
第二个group的daemon被设置为true,当其中没有active线程的时候,改group将会被自动destroy,而第二个则不会