配色: 字号:
ThreadGroup线程组应用
2016-10-12 | 阅:  转:  |  分享 
  
ThreadGroup线程组应用



一、基本方法

1、获取当前线程组名

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

Thread.currentThread().getThreadGroup().getName()

在main方法是调用输出是:main

2、将线程放入到一个线程组中去

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

ThreadGroupthreadGroup1=newThreadGroup("group1");

ThreadGroupthreadGroup2=newThreadGroup("group2");

Threadthread1=newThread(threadGroup1,"group1''smember");

Threadthread2=newThread(threadGroup2,"group2''smember");

其中Thread中和ThreadGroup相关的构造函数:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicThread(ThreadGroupgroup,Runnabletarget){

init(group,target,"Thread-"+nextThreadNum(),0);

}





publicThread(ThreadGroupgroup,Stringname){

init(group,null,name,0);

}





publicThread(ThreadGroupgroup,Runnabletarget,Stringname){

init(group,target,name,0);

}



publicThread(ThreadGroupgroup,Runnabletarget,Stringname,

longstackSize){

init(group,target,name,stackSize);

}

它们最终都是调用同一个函数:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

privatevoidinit(ThreadGroupg,Runnabletarget,Stringname,

longstackSize){

Threadparent=currentThread();

SecurityManagersecurity=System.getSecurityManager();

if(g==null){

//安全检查

if(security!=null){

g=security.getThreadGroup();

}



//设置线程组

if(g==null){

g=parent.getThreadGroup();

}

}



//检查可达性

g.checkAccess();



//是否有权限访问

if(security!=null){

if(isCCLOverridden(getClass())){

security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);

}

}



//往线程组添加线程但未启动

g.addUnstarted();



this.group=g;

this.daemon=parent.isDaemon();//是否守护线程

this.priority=parent.getPriority();//优先级

this.name=name.toCharArray();

if(security==null||isCCLOverridden(parent.getClass()))

this.contextClassLoader=parent.getContextClassLoader();

else

this.contextClassLoader=parent.contextClassLoader;

this.inheritedAccessControlContext=AccessController.getContext();

this.target=target;

setPriority(priority);

if(parent.inheritableThreadLocals!=null)

this.inheritableThreadLocals=

ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

this.stackSize=stackSize;

tid=nextThreadID();

this.me=this;

}



3、复制线程组:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

//这样可以复制group里面的thread信息

Thread[]threads=newThread[threadGroup.activeCount()];

threadGroup.enumerate(threads);

这里的activeCount很明显就是取得活动的线程,注意。默认情况下,连同其子线程组也会进行复制。



4、未捕获异常处理

ThreadGroup中有一个uncaughtException()方法。当线程组中某个线程发生Uncheckedexception异常时,由执行环境调用此方法进行相关处理,如果有必要,可以重新定义此方法



二、应用实例

1、实例应用

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

packagecom.func.axc.threadgroup;





importjava.util.Date;

importjava.util.Random;

importjava.util.concurrent.TimeUnit;



classResult{



privateStringname;



publicStringgetName(){

returnname;

}



publicvoidsetName(Stringname){

this.name=name;

}



}



publicclassSearchTaskimplementsRunnable{



publicSearchTask(Resultresult){

this.result=result;

}



privateResultresult;



@Override

publicvoidrun(){

Stringname=Thread.currentThread().getName();

System.out.println("ThreadStart"+name);

try{

doTask();

result.setName(name);

}catch(InterruptedExceptione){

System.out.printf("Thread%s:Interrupted\n",name);

return;

}

System.out.println("Threadend"+name);

}



privatevoiddoTask()throwsInterruptedException{

Randomrandom=newRandom((newDate()).getTime());

intvalue=(int)(random.nextDouble()100);

System.out.printf("Thread%s:%d\n",Thread.currentThread().getName(),

value);

TimeUnit.SECONDS.sleep(value);

}



publicstaticvoidmain(String[]args){

System.out.println("mainthreadstart:");



//创建5个线程,并入group里面进行管理

ThreadGroupthreadGroup=newThreadGroup("Searcher");

Resultresult=newResult();

SearchTasksearchTask=newSearchTask(result);

for(inti=0;i<5;i++){

Threadthred=newThread(threadGroup,searchTask);

thred.start();

try{

TimeUnit.SECONDS.sleep(1);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

//通过这种方法可以看group里面的所有信息

System.out.printf("NumberofThreads:%d\n",threadGroup.activeCount());

System.out.printf("InformationabouttheThreadGroup\n");

threadGroup.list();



//这样可以复制group里面的thread信息

Thread[]threads=newThread[threadGroup.activeCount()];

threadGroup.enumeratewww.baiyuewang.net(threads);

for(inti=0;i
System.out.printf("Thread%s:%s\n",threads[i].getName(),

threads[i].getState());

}



waitFinish(threadGroup);

//将group里面的所有线程都给interpet

threadGroup.interrupt();



System.out.println("mainthreadend:");

}



privatestaticvoidwaitFinish(ThreadGroupthreadGroup){

while(threadGroup.activeCount()>0){

try{

TimeUnit.SECONDS.sleep(1);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

}



}

输出结果:





2、统一异常处理实例

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

packagecom.func.axc.threadgroup;



/

功能概要:



@authorlinbingwen

@since2016年6月11日

/

publicclassThreadGroupDemo{



publicstaticvoidmain(String[]args){

ThreadGroupthreadGroup1=

//这是匿名类写法

newThreadGroup("group1"){

//继承ThreadGroup并重新定义以下方法

//在线程成员抛出uncheckedexception

//会执行此方法

publicvoiduncaughtException(Threadt,Throwablee){

System.out.println(t.getName()+":"+e.getMessage());

}

};

//这是匿名类写法

Threadthread1=

//这个线程是threadGroup1的一员

newThread(threadGroup1,newRunnable(){

publicvoidrun(){

//抛出unchecked异常

thrownewRuntimeException("测试异常");

}

});



thread1.start();

}



}



三、源码解读

首先看其包含的变量

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassThreadGroupimplementsThread.UncaughtExceptionHandler{

privatefinalThreadGroupparent;//父亲ThreadGroup

Stringname;//ThreadGroupr的名称

intmaxPriority;//线程最大优先级

booleandestroyed;//是否被销毁

booleandaemon;//是否守护线程

booleanvmAllowSuspension;//是否可以中断



intnUnstartedThreads=0;//还未启动的线程

intnthreads;//ThreadGroup中线程数目

Threadthreads[];//ThreadGroup中的线程



intngroups;//线程组数目

ThreadGroupgroups[];//线程组数组



从源码中可以看出,其包含的变量并不是很多。这里需要注意

(1)线程组也可以包含其他线程组。如上面的groups[].

(2)线程组构成一棵树,在树中,除了初始线程组外,每个线程组都有一个父线程组

构造函数:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

//私有构造函数

privateThreadGroup(){

this.name="system";

this.maxPriority=Thread.MAX_PRIORITY;

this.parent=null;

}



//默认是以当前ThreadGroup传入作为parentThreadGroup,新线程组的父线程组是目前正在运行线程的线程组。

publicThreadGroup(Stringname){

this(Thread.currentThread().getThreadGroup(),name);

}



//构造函数

publicThreadGroup(ThreadGroupparent,Stringname){

this(checkParentAccess(parent),parent,name);

}



//私有构造函数

privateThreadGroup(Voidunused,ThreadGroupparent,Stringname){

this.name=name;

this.maxPriority=parent.maxPriority;

this.daemon=parent.daemon;

this.vmAllowSuspension=parent.vmAllowSuspension;

this.parent=parent;

parent.add(this);

}

其终的调用构造函数只有一个,父线程组的checkAccess方法在checkParentAccess中会调用:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

//检查parentThreadGroup

privatestaticVoidcheckParentAccess(ThreadGroupparent){

parent.checkAccess();

returnnull;

}

未捕获异常设置:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicvoiduncaughtException(Threadt,Throwablee){

if(parent!=null){

parent.uncaughtException(t,e);//父线程组不为空,设置到父线程组

}else{

Thread.UncaughtExceptionHandlerueh=

Thread.getDefaultUncaughtExceptionHandler();

if(ueh!=null){

ueh.uncaughtException(t,e);

}elseif(!(einstanceofThreadDeath)){

System.err.print("Exceptioninthread\""

+t.getName()+"\"");

e.printStackTrace(System.err);

}

}

}

如果父线程组存在,则调用它的uncaughtException方法.

如果父线程组不存在,但指定了默认处理器(下节中的Asthedefaulthandlerfortheapplication),则调用默认的处理器

如果默认处理器没有设置,则写错误日志.但如果exception是ThreadDeath实例的话,忽略



线程组复制:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

//此线程组及其子组中的所有活动线程复制到指定数组中。

publicintenumerate(ThreadGrouplist[]){

checkAccess();

returnenumerate(list,0,true);

}

//此线程组及其子组中的所有活动线程复制到指定数组中。

publicintenumerate(ThreadGrouplist[],booleanrecurse){

checkAccess();

returnenumerate(list,0,recurse);

}

//此线程组中的所有活动线程复制到指定数组中。如果recurse标志为true,则还包括对此线程的子组中的所有活动线程的引用。如果数组太小而无法保持所有线程,则//忽略额外的线程。

privateintenumerate(ThreadGrouplist[],intn,booleanrecurse){

intngroupsSnapshot=0;

ThreadGroup[]groupsSnapshot=null;

synchronized(this){

if(destroyed){

return0;

}

intng=ngroups;

if(ng>list.length-n){//防止list放不下线程数目

ng=list.length-n;

}

if(ng>0){

System.arraycopy(groups,0,list,n,ng);//复制线程组

n+=ng;

}

if(recurse){//取得其子组

ngroupsSnapshot=ngroups;

if(groups!=null){

groupsSnapshot=Arrays.copyOf(groups,ngroupsSnapshot);

}else{

groupsSnapshot=null;

}

}

}

if(recurse){//复制子组

for(inti=0;i
n=groupsSnapshot[i].enumerate(list,n,true);

}

}

returnn;

}



献花(0)
+1
(本文系thedust79首藏)