Java中線程組ThreadGroup與線程池的區(qū)別及示例
線程組概念理解
在java的多線程處理中有線程組ThreadGroup的概念,ThreadGroup是為了方便線程管理出現(xiàn)了,可以統(tǒng)一設定線程組的一些屬性,比如setDaemon,設置未處理異常的處理方法,設置統(tǒng)一的安全策略等等;也可以通過線程組方便的獲得線程的一些信息。
每一個ThreadGroup都可以包含一組的子線程和一組子線程組,在一個進程中線程組是以樹形的方式存在,通常情況下根線程組是system線程組。system線程組下是main線程組,默認情況下第一級應用自己的線程組是通過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)建線程時可能不設置線程組,這時候創(chuàng)建的線程會和創(chuàng)建該線程的線程在一個組里面。
線程組實踐
下面通過實例演示如何使用ThreadGroup,該實例中設定了線程組的Daemon屬性,設置了線程組內(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)一設定線程是否為守護線程
spiderGroup.setDaemon(true);
//可以設置線程組內(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進行了特殊處理
* @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)一處理了。
下面我們通過另外一個示例演示如何通過線程組,方便的獲得應用中一共有多少個活動線程,并打印這些活動線程的名字。
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所在的線程,其他都是虛擬機啟動的線程。是不是出乎你的意外了?
線程組和線程池的區(qū)別
線程組和線程池是兩個不同的概念,他們的作用完全不同,線程組是為了方便線程的管理,線程池是為了管理線程的生命周期,復用線程,減少創(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)文章
SSH框架網(wǎng)上商城項目第29戰(zhàn)之使用JsChart技術(shù)顯示商品銷售報表
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第29戰(zhàn)之使用JsChart技術(shù)顯示商品銷售報表,感興趣的小伙伴們可以參考一下2016-06-06
Java實戰(zhàn)小技巧之數(shù)組與list互轉(zhuǎn)
在Java中,經(jīng)常遇到需要List與數(shù)組互相轉(zhuǎn)換的場景,下面這篇文章主要給大家介紹了關(guān)于Java實戰(zhàn)小技巧之數(shù)組與list互轉(zhuǎn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2021-08-08
Spring boot2X負載均衡和反向代理實現(xiàn)過程解析
這篇文章主要介紹了Spring boot2X負載均衡和反向代理實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12

