Java中線程組ThreadGroup與線程池的區(qū)別及示例
線程組概念理解
在java的多線程處理中有線程組ThreadGroup的概念,ThreadGroup是為了方便線程管理出現(xiàn)了,可以統(tǒng)一設(shè)定線程組的一些屬性,比如setDaemon,設(shè)置未處理異常的處理方法,設(shè)置統(tǒng)一的安全策略等等;也可以通過線程組方便的獲得線程的一些信息。
每一個ThreadGroup都可以包含一組的子線程和一組子線程組,在一個進(jìn)程中線程組是以樹形的方式存在,通常情況下根線程組是system線程組。system線程組下是main線程組,默認(rèn)情況下第一級應(yīng)用自己的線程組是通過main線程組創(chuàng)建出來的。
我們可以通過下面代碼片段看下一個簡單的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("--------------------------");
}
}這段代碼打印結(jié)果如下:
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
在創(chuàng)建線程時可以通過構(gòu)造函數(shù)指定其所在的線程組,如下代碼:
ThreadGroup group=new ThreadGroup("worker");
Thread thread=new Thread(group,"the first thread of group");通常情況下我們創(chuàng)建線程時可能不設(shè)置線程組,這時候創(chuàng)建的線程會和創(chuàng)建該線程的線程在一個組里面。
線程組實踐
下面通過實例演示如何使用ThreadGroup,該實例中設(shè)定了線程組的Daemon屬性,設(shè)置了線程組內(nèi)線程的最大優(yōu)先級,通過繼承ThreadGroup的方式,重寫了該線程組對于未處理異常的處理邏輯。
請看下面代碼:
package cn.outofmemory.concurrent;
import java.net.SocketException;
public class ThreadGroupDemo2 {
public static void main(String[] args) {
ThreadGroup spiderGroup = new SpiderThreadGroup("spiderGroup");
//可以統(tǒng)一設(shè)定線程是否為守護(hù)線程
spiderGroup.setDaemon(true);
//可以設(shè)置線程組內(nèi)的最大優(yōu)先級
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進(jìn)行了特殊處理
* @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);
}
}
}
}上面的實例代碼會輸出如下內(nèi)容:
socket exception should be process
說明未處理異常已經(jīng)被統(tǒng)一處理了。
下面我們通過另外一個示例演示如何通過線程組,方便的獲得應(yīng)用中一共有多少個活動線程,并打印這些活動線程的名字。
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;
}
//現(xiàn)在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());
}
}
}你不妨猜猜這個小程序的輸出結(jié)果,按理說我只有一個main方法,沒有任何自定義線程,那么會輸出幾個線程呢?
下面是輸出結(jié)果:
active count is 5 Reference Handler Finalizer Signal Dispatcher Attach Listener main
一共有5個線程,這5個線程除了main是我們自己代碼run所在的線程,其他都是虛擬機(jī)啟動的線程。是不是出乎你的意外了?
線程組和線程池的區(qū)別
線程組和線程池是兩個不同的概念,他們的作用完全不同,線程組是為了方便線程的管理,線程池是為了管理線程的生命周期,復(fù)用線程,減少創(chuàng)建銷毀線程的開銷。
在構(gòu)建線程池時,ThreadPoolExcutor的構(gòu)造方法中,生成線程工廠的參數(shù)ThreadFactory接口的實現(xiàn)類DefaultThreadFactory中有個屬性,ThreadGroup
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
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;
......
}到此這篇關(guān)于Java中線程組ThreadGroup與線程池的區(qū)別及示例的文章就介紹到這了,更多相關(guān)Java 線程組ThreadGroup內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot以FTP方式上傳文件到遠(yuǎn)程服務(wù)器
這篇文章主要介紹了springboot以FTP方式上傳文件到遠(yuǎn)程服務(wù)器,需要的朋友可以參考下2019-12-12
SpringBoot 集成Kaptcha實現(xiàn)驗證碼功能實例詳解
在一個web應(yīng)用中驗證碼是一個常見的元素。今天給大家介紹一下kaptcha的和springboot一起使用的簡單例子。感興趣的朋友參考下吧2017-08-08

