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("--------------------------"); } }
這段代碼打印結果如下:
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)建線程時可以通過構造函數(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()); } } }
你不妨猜猜這個小程序的輸出結果,按理說我只有一個main方法,沒有任何自定義線程,那么會輸出幾個線程呢?
下面是輸出結果:
active count is 5 Reference Handler Finalizer Signal Dispatcher Attach Listener main
一共有5個線程,這5個線程除了main是我們自己代碼run所在的線程,其他都是虛擬機啟動的線程。是不是出乎你的意外了?
線程組和線程池的區(qū)別
線程組和線程池是兩個不同的概念,他們的作用完全不同,線程組是為了方便線程的管理,線程池是為了管理線程的生命周期,復用線程,減少創(chuàng)建銷毀線程的開銷。
在構建線程池時,ThreadPoolExcutor的構造方法中,生成線程工廠的參數(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; ...... }
到此這篇關于Java中線程組ThreadGroup與線程池的區(qū)別及示例的文章就介紹到這了,更多相關Java 線程組ThreadGroup內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SSH框架網(wǎng)上商城項目第29戰(zhàn)之使用JsChart技術顯示商品銷售報表
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第29戰(zhàn)之使用JsChart技術顯示商品銷售報表,感興趣的小伙伴們可以參考一下2016-06-06Java實戰(zhàn)小技巧之數(shù)組與list互轉(zhuǎn)
在Java中,經(jīng)常遇到需要List與數(shù)組互相轉(zhuǎn)換的場景,下面這篇文章主要給大家介紹了關于Java實戰(zhàn)小技巧之數(shù)組與list互轉(zhuǎn)的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2021-08-08Spring boot2X負載均衡和反向代理實現(xiàn)過程解析
這篇文章主要介紹了Spring boot2X負載均衡和反向代理實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12