日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java守护线程概述

發(fā)布時間:2024/4/11 java 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java守护线程概述 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計與實踐原理》和《RabbitMQ實戰(zhàn)指南》,同時歡迎關(guān)注筆者的微信公眾號:朱小廝的博客。

歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/java-daemon-thread/

Java的線程分為兩種:User Thread(用戶線程)、DaemonThread(守護線程)。

只要當前JVM實例中尚存任何一個非守護線程沒有結(jié)束,守護線程就全部工作;只有當最后一個非守護線程結(jié)束是,守護線程隨著JVM一同結(jié)束工作,Daemon作用是為其他線程提供便利服務(wù),守護線程最典型的應(yīng)用就是GC(垃圾回收器),他就是一個很稱職的守護者。

User和Daemon兩者幾乎沒有區(qū)別,唯一的不同之處就在于虛擬機的離開:如果 User Thread已經(jīng)全部退出運行了,只剩下Daemon Thread存在了,虛擬機也就退出了。 因為沒有了被守護者,Daemon也就沒有工作可做了,也就沒有繼續(xù)運行程序的必要了。

首先看一個例子,主線程中建立一個守護線程,當主線程結(jié)束時,守護線程也跟著結(jié)束。

?

package com.daemon;import java.util.concurrent.TimeUnit;public class DaemonThreadTest {public static void main(String[] args){Thread mainThread = new Thread(new Runnable(){@Overridepublic void run(){Thread childThread = new Thread(new ClildThread());childThread.setDaemon(true);childThread.start();System.out.println("I'm main thread...");}});mainThread.start();} }class ClildThread implements Runnable {@Overridepublic void run(){while(true){System.out.println("I'm child thread..");try{TimeUnit.MILLISECONDS.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}} }

運行結(jié)果:

?

?

I'm child thread.. I'm main thread...

如果不何止childThread為守護線程,當主線程結(jié)束時,childThread還在繼續(xù)運行,如下:

package com.daemon;import java.util.concurrent.TimeUnit;public class DaemonThreadTest {public static void main(String[] args){Thread mainThread = new Thread(new Runnable(){@Overridepublic void run(){Thread childThread = new Thread(new ClildThread());childThread.setDaemon(false);childThread.start();System.out.println("I'm main thread...");}});mainThread.start();} }class ClildThread implements Runnable {@Overridepublic void run(){while(true){System.out.println("I'm child thread..");try{TimeUnit.MILLISECONDS.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}} }

運行結(jié)果:

?

?

I'm main thread... I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread..(無限輸出)

可以看到,當主線程結(jié)束時,childThread是非守護線程,就會無限的執(zhí)行。

?

守護線程有一個應(yīng)用場景,就是當主線程結(jié)束時,結(jié)束其余的子線程(守護線程)自動關(guān)閉,就免去了還要繼續(xù)關(guān)閉子線程的麻煩。不過博主推薦,如果真有這種場景,還是用中斷的方式實現(xiàn)比較合理。

還有補充一點,不是說當子線程是守護線程,主線程結(jié)束,子線程就跟著結(jié)束,這里的前提條件是:當前jvm應(yīng)用實例中沒有用戶線程繼續(xù)執(zhí)行,如果有其他用戶線程繼續(xù)執(zhí)行,那么后臺線程不會中斷,如下:

package com.daemon;import java.util.concurrent.TimeUnit;public class DaemonThreadTest {public static void main(String[] args){Thread mainThread = new Thread(new Runnable(){@Overridepublic void run(){Thread childThread = new Thread(new ClildThread());childThread.setDaemon(true);childThread.start();System.out.println("I'm main thread...");}});mainThread.start();Thread otherThread = new Thread(new Runnable(){@Overridepublic void run(){while(true){System.out.println("I'm other user thread...");try{TimeUnit.MILLISECONDS.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}});otherThread.start();} }class ClildThread implements Runnable {@Overridepublic void run(){while(true){System.out.println("I'm child thread..");try{TimeUnit.MILLISECONDS.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}} }

運行結(jié)果:

I'm other user thread... I'm child thread.. I'm main thread... I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread.. I'm child thread.. I'm other user thread... I'm other user thread... I'm child thread.. I'm child thread.. I'm other user thread... I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread.. I'm other user thread... I'm child thread..(無限輸出)

如果需要在主線程結(jié)束時,將子線程結(jié)束掉,可以采用如下的中斷方式:

?

?

package com.self;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;public class ThreadTest {public static void main(String[] args){Thread mainThread = new Thread(new Runnable(){public void run(){System.out.println("主線程開始...");Thread sonThread = new Thread(new Thread1(Thread.currentThread()));sonThread.setDaemon(false);sonThread.start();try{TimeUnit.MILLISECONDS.sleep(10000);}catch (InterruptedException e){e.printStackTrace();}System.out.println("主線程結(jié)束");}});mainThread.start();}}class Thread1 implements Runnable {private Thread mainThread;public Thread1(Thread mainThread){this.mainThread = mainThread;}@Overridepublic void run(){while(mainThread.isAlive()){System.out.println("子線程運行中....");try{TimeUnit.MILLISECONDS.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}}

運行結(jié)果:

?

?

主線程開始... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 子線程運行中.... 主線程結(jié)束


回歸正題,這里有幾點需要注意:
(1) thread.setDaemon(true)必須在thread.start()之前設(shè)置,否則會跑出一個IllegalThreadStateException異常。你不能把正在運行的常規(guī)線程設(shè)置為守護線程。
(2) 在Daemon線程中產(chǎn)生的新線程也是Daemon的。?
(3) 不要認為所有的應(yīng)用都可以分配給Daemon來進行服務(wù),比如讀寫操作或者計算邏輯。

?

?

?

寫java多線程程序時,一般比較喜歡用java自帶的多線程框架,比如ExecutorService,但是java的線程池會將守護線程轉(zhuǎn)換為用戶線程,所以如果要使用后臺線程就不能用java的線程池。

如下,線程池中將daemon線程轉(zhuǎn)換為用戶線程的程序片段:

static class DefaultThreadFactory implements ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);private final ThreadGroup group;private final AtomicInteger threadNumber = new AtomicInteger(1);private final String namePrefix;DefaultThreadFactory() {SecurityManager s = System.getSecurityManager();group = (s != null) ? s.getThreadGroup() :Thread.currentThread().getThreadGroup();namePrefix = "pool-" +poolNumber.getAndIncrement() +"-thread-";}public Thread newThread(Runnable r) {Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);if (t.isDaemon())t.setDaemon(false);if (t.getPriority() != Thread.NORM_PRIORITY)t.setPriority(Thread.NORM_PRIORITY);return t;}}

注意到,這里不僅會將守護線程轉(zhuǎn)變?yōu)橛脩艟€程,而且會把優(yōu)先級轉(zhuǎn)變?yōu)門hread.NORM_PRIORITY。

?

如下所示,將守護線程采用線程池的方式開啟:

?

package com.daemon;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;public class DaemonThreadTest {public static void main(String[] args){Thread mainThread = new Thread(new Runnable(){@Overridepublic void run(){ExecutorService exec = Executors.newCachedThreadPool();Thread childThread = new Thread(new ClildThread());childThread.setDaemon(true);exec.execute(childThread);exec.shutdown();System.out.println("I'm main thread...");}});mainThread.start();} }class ClildThread implements Runnable {@Overridepublic void run(){while(true){System.out.println("I'm child thread..");try{TimeUnit.MILLISECONDS.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}} }

運行結(jié)果:

?

?

I'm main thread... I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread.. I'm child thread..(無限輸出)

上面代碼證實了線程池會將守護線程轉(zhuǎn)變?yōu)橛脩艟€程。

?

至于為什么jdk會這么做,博主還沒有參悟的透徹,如果你了解,希望能留言告知。
?

歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/java-daemon-thread/

歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計與實踐原理》和《RabbitMQ實戰(zhàn)指南》,同時歡迎關(guān)注筆者的微信公眾號:朱小廝的博客。

總結(jié)

以上是生活随笔為你收集整理的Java守护线程概述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。