欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

【java 多線程】守護(hù)線程與非守護(hù)線程的詳解

 更新時(shí)間:2019年04月28日 15:09:37   作者:紫仙空靈  
這篇文章主要介紹了java守護(hù)線程與非守護(hù)線程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Java中有兩類線程:User Thread(用戶線程)、Daemon Thread(守護(hù)線程)

用戶線程即運(yùn)行在前臺(tái)的線程,而守護(hù)線程是運(yùn)行在后臺(tái)的線程。 守護(hù)線程作用是為其他前臺(tái)線程的運(yùn)行提供便利服務(wù),而且僅在普通、非守護(hù)線程仍然運(yùn)行時(shí)才需要,比如垃圾回收線程就是一個(gè)守護(hù)線程。當(dāng)VM檢測僅剩一個(gè)守護(hù)線程,而用戶線程都已經(jīng)退出運(yùn)行時(shí),VM就會(huì)退出,因?yàn)闆]有如果沒有了被守護(hù)這,也就沒有繼續(xù)運(yùn)行程序的必要了。如果有非守護(hù)線程仍然存活,VM就不會(huì)退出。

守護(hù)線程并非只有虛擬機(jī)內(nèi)部提供,用戶在編寫程序時(shí)也可以自己設(shè)置守護(hù)線程。用戶可以用Thread的setDaemon(true)方法設(shè)置當(dāng)前線程為守護(hù)線程。

雖然守護(hù)線程可能非常有用,但必須小心確保其他所有非守護(hù)線程消亡時(shí),不會(huì)由于它的終止而產(chǎn)生任何危害。因?yàn)槟悴豢赡苤涝谒械挠脩艟€程退出運(yùn)行前,守護(hù)線程是否已經(jīng)完成了預(yù)期的服務(wù)任務(wù)。一旦所有的用戶線程退出了,虛擬機(jī)也就退出運(yùn)行了。 因此,不要在守護(hù)線程中執(zhí)行業(yè)務(wù)邏輯操作(比如對數(shù)據(jù)的讀寫等)。、

另外有幾點(diǎn)需要注意:

  1. 1、setDaemon(true)必須在調(diào)用線程的start()方法之前設(shè)置,否則會(huì)拋出IllegalThreadStateException異常。
  2. 2、在守護(hù)線程中產(chǎn)生的新線程也是守護(hù)線程。
  3. 3、 不要認(rèn)為所有的應(yīng)用都可以分配給守護(hù)線程來進(jìn)行服務(wù),比如讀寫操作或者計(jì)算邏輯。

Timer代碼示例:

package day003;

import java.util.Date;
import java.util.TimerTask;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:MyTask
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:05:28
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:05:28
* 修改備注:
* @version
*
*/
public class MyTask extends TimerTask{

 /**
 * (non-Javadoc)
 * @see java.util.TimerTask#run()
 */
 public void run() {
   System.out.println("任務(wù)執(zhí)行了,時(shí)間為:"+new Date());
 }
}
-----------------------------------------------------------------------------------
package day003;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:TimerTaskRun
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:08:01
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:08:01
* 修改備注:
* @version
*
*/
public class TimerTaskRun {
 public static void main(String[] args) {
  System.out.println("系統(tǒng)當(dāng)前時(shí)間:"+new Date());
  Calendar calendar = Calendar.getInstance();
  calendar.add(Calendar.SECOND, 10);
  Date date = calendar.getTime();
  MyTask task = new MyTask();
  Timer timer = new Timer();
  timer.schedule(task, date);
 }
}

運(yùn)行結(jié)果:

系統(tǒng)當(dāng)前時(shí)間:Mon Mar 19 15:11:47 CST 2018
任務(wù)執(zhí)行了,時(shí)間為:Mon Mar 19 15:11:57 CST 2018

 任務(wù)雖然運(yùn)行完了,但進(jìn)程還未銷毀,呈紅色狀態(tài),為什么會(huì)出現(xiàn)這種情況呢?

可以看一下Timer的源碼

/**
  * Creates a new timer. The associated thread does <i>not</i>
  * {@linkplain Thread#setDaemon run as a daemon}.
  */
 public Timer() {
  this("Timer-" + serialNumber());
 }


 /**
  * Creates a new timer whose associated thread has the specified name.
  * The associated thread does <i>not</i>
  * {@linkplain Thread#setDaemon run as a daemon}.
  *
  * @param name the name of the associated thread
  * @throws NullPointerException if {@code name} is null
  * @since 1.5
  */
 public Timer(String name) {
  thread.setName(name);
  thread.start();
 }

 可以看出每創(chuàng)建一個(gè)Timer就是啟動(dòng)一個(gè)新的線程,那么啟動(dòng)的線程不是守護(hù)線程,所以一直運(yùn)行。那我們該如何將 新創(chuàng)建的的Timer改成守護(hù)線程呢?更改如上的代碼:

package day003;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:TimerTaskRun
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:08:01
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:08:01
* 修改備注:
* @version
*
*/
public class TimerTaskRun {
 public static void main(String[] args) {
  System.out.println("系統(tǒng)當(dāng)前時(shí)間:"+new Date());
  Calendar calendar = Calendar.getInstance();
  calendar.add(Calendar.SECOND, 10);
  Date date = calendar.getTime();
  MyTask task = new MyTask();
  Timer timer = new Timer(true);
  timer.schedule(task, date);
 }
}

運(yùn)行結(jié)果如下:

系統(tǒng)當(dāng)前時(shí)間:Mon Mar 19 15:21:42 CST 2018

 

守護(hù)線程中產(chǎn)生的線程也是守護(hù)線程
如下示例:

package day003;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:Daemon
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:30:53
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:30:53
* 修改備注:
* @version
*
*/
public class Daemon implements Runnable {
 private Thread[] t = new Thread[10];

 /**
 * (non-Javadoc)
 * @see java.lang.Runnable#run()
 */
 public void run() {
  for (int i = 0; i < t.length; i++) {
   t[i] = new Thread(new DaemonSpawn());
   t[i].start();
   System.out.println("DaemonSpawn " + i + " started.");
  }
  for (int i = 0; i < t.length; i++) {
   System.out.println("t[" + i + "].isDaemon() = " + t[i].isDaemon() + ".");
  }
  while (true) {
   Thread.yield();
  }
 }
}
-----------------------------------------------------------------------------------
package day003;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:DaemonSpawn
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:32:06
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:32:06
* 修改備注:
* @version
*
*/
public class DaemonSpawn implements Runnable {

 /**
 * (non-Javadoc)
 * @see java.lang.Runnable#run()
 */
 public void run() {
  while (true) {
   Thread.yield();
  }
 }
}
-----------------------------------------------------------------------------------
package day003;

import java.util.concurrent.TimeUnit;
/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:DaemonRun
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:36:34
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:36:34
* 修改備注:
* @version
*
*/
public class DaemonRun {
 public static void main(String[] args) throws InterruptedException {
  Thread d = new Thread(new Daemon());
  d.setDaemon(true);//必須在啟動(dòng)線程前調(diào)用
  d.start();
  System.out.println("d.isDaemon() = " + d.isDaemon() + ".");
  TimeUnit.SECONDS.sleep(1);
 }
}

 運(yùn)行結(jié)果如圖:

d.isDaemon() = true.
DaemonSpawn 0 started.
DaemonSpawn 1 started.
DaemonSpawn 2 started.
DaemonSpawn 3 started.
DaemonSpawn 4 started.
DaemonSpawn 5 started.
DaemonSpawn 6 started.
DaemonSpawn 7 started.
DaemonSpawn 8 started.
DaemonSpawn 9 started.
t[0].isDaemon() = true.
t[1].isDaemon() = true.
t[2].isDaemon() = true.
t[3].isDaemon() = true.
t[4].isDaemon() = true.
t[5].isDaemon() = true.
t[6].isDaemon() = true.
t[7].isDaemon() = true.
t[8].isDaemon() = true.
t[9].isDaemon() = true.

 如果將mian函數(shù)中的TimeUnit.SECONDS.sleep(1);注釋掉,看一下TimeUnit.SECONDS.sleep()的源碼:

/**
  * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
  * this time unit.
  * This is a convenience method that converts time arguments into the
  * form required by the {@code Thread.sleep} method.
  *
  * @param timeout the minimum time to sleep. If less than
  * or equal to zero, do not sleep at all.
  * @throws InterruptedException if interrupted while sleeping
  */
 public void sleep(long timeout) throws InterruptedException {
  if (timeout > 0) {
   long ms = toMillis(timeout);
   int ns = excessNanos(timeout, ms);
   Thread.sleep(ms, ns);
  }
 }

其實(shí)就是對Thread.sleep()的封裝,提供了可讀性更好的線程暫停操作

注釋后代碼運(yùn)行如下:

d.isDaemon() = true.

以上結(jié)果也說明了如果用戶線程全部退出了,只剩下守護(hù)線程存在了,虛擬機(jī)也就退出了。

典型的守護(hù)線程是(GC)垃圾回收線程。

package day003;


/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:MyThread
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午3:50:12
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午3:50:12
* 修改備注:
* @version
*
*/
public class MyThread extends Thread{
 private int i = 0;
 /**
 * (non-Javadoc)
 * @see java.lang.Thread#run()
 */

 public void run() {
  super.run();
  try {
   while (true) {
    i++;
    System.out.println("i="+i);
    Thread.sleep(1000);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }

 }

 public static void main(String[] args) throws InterruptedException {
  MyThread daemonThread = new MyThread();
  daemonThread.setDaemon(true);
  daemonThread.start();
  Thread.sleep(5000);
  System.out.println("當(dāng)main線程執(zhí)行完畢,守護(hù)線程也停止了。");
 }
}

運(yùn)行結(jié)果:

i=1
i=2
i=3
i=4
i=5
當(dāng)main線程執(zhí)行完畢,守護(hù)線程也停止了。

 除 JVM 內(nèi)部的守護(hù)線程外,用戶可以通過以下方法設(shè)置守護(hù)線程:

public final void setDaemon(boolean on)

可以通過以下方法查詢線程是否為守護(hù)線程:

public final boolean isDaemon()

關(guān)于守護(hù)線程的幾個(gè)要點(diǎn):

1、setDaemon 方法必須在 thread.start() 之前設(shè)置,否則會(huì)拋出 java.lang.IllegalThreadStateException 異常,不能將正在運(yùn)行的常規(guī)線程設(shè)置為守護(hù)線程

package day003;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:TestDaemon
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午4:01:32
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午4:01:32
* 修改備注:
* @version
*
*/
public class TestDaemon {
 public static void main(String[] args) {
  Thread thread = new Thread();
  thread.start();
  thread.setDaemon(true);
 }
}

運(yùn)行結(jié)果:

Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1359)
at day003.TestDaemon.main(TestDaemon.java:32)

 2、不是所有的應(yīng)用都可以分配給 Daemon 線程來進(jìn)行服務(wù),比如讀寫操作或者計(jì)算邏輯,因?yàn)樵?Daemon 線程還沒來的及進(jìn)行操作時(shí)虛擬機(jī)可能已經(jīng)退出了

package day003;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:TestDaemon2
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午4:03:22
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午4:03:22
* 修改備注:
* @version
*
*/
public class TestDaemon2 extends Thread{

 /**
 * (non-Javadoc)
 * @see java.lang.Thread#run()
 */

 public void run() {
  super.run();
  FileOutputStream outputStream = null;
  try {
   Thread.sleep(3000);
   File file = new File("daemon.txt");
   outputStream = new FileOutputStream(file);
   outputStream.write("daemon".getBytes());
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   if (outputStream != null) {
    try {
     outputStream.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }
 public static void main(String[] args) {
  Thread thread = new TestDaemon2();
  thread.setDaemon(true);
  thread.start();
 }

以上代碼中線程功能是向工程根目錄的“daemon.txt”文件寫入字符串“daemon”,實(shí)際運(yùn)行結(jié)果發(fā)現(xiàn)并未成功寫入,且未報(bào)任何錯(cuò)誤,原因是寫入文件的線程被設(shè)置為守護(hù)線程,該線程還在 sleep 過程中時(shí)所有用戶線程就全部結(jié)束了,守護(hù)線程也會(huì)隨著 JVM 一起退出。

如果將上面代碼中的thread.setDaemon(true);注釋掉,

 public static void main(String[] args) {
  Thread thread = new TestDaemon2();
  //thread.setDaemon(true);
  thread.start();
 }

不將線程設(shè)置為守護(hù)線程可以在工程根目錄的“daemon.txt”文件中看到字符串“daemon”

示例2:

package day003;

/**
*
* 項(xiàng)目名稱:JavaThread
* 類名稱:CustomThread
* 類描述:
* 創(chuàng)建人:liuc
* 創(chuàng)建時(shí)間:2018年3月19日 下午4:16:42
* 修改人:liuc
* 修改時(shí)間:2018年3月19日 下午4:16:42
* 修改備注:
* @version
*
*/
public class CustomThread extends Thread {

 /**
 * (non-Javadoc)
 * @see java.lang.Thread#run()
 */
 public void run() {
  super.run();
  for (int i = 0; i < 100; i++) {
   System.out.println("Daemon Thread : " + i);
  }
 }

 public static void main(String[] args) {
  Thread daemonThread = new CustomThread();
  daemonThread.setDaemon(true);
  Thread userThread = new Thread();
  daemonThread.start();
  userThread.start();
 }
}

多次執(zhí)行示例2代碼,控制臺(tái)要么不打印任何信息,要么打印一部分循環(huán)的輸出信息就結(jié)束了,從運(yùn)行結(jié)果可以看出,守護(hù)線程并未執(zhí)行完成所有循環(huán)就結(jié)束了,因?yàn)橛脩艟€程在守護(hù)線程執(zhí)行循環(huán)的過程中就已全部結(jié)束,守護(hù)線程也隨著 JVM 一起結(jié)束。

以上所述是小編給大家介紹的java守護(hù)線程與非守護(hù)線程詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Java核心庫實(shí)現(xiàn)簡單的AOP

    Java核心庫實(shí)現(xiàn)簡單的AOP

    這篇文章主要介紹了如何用Java核心庫實(shí)現(xiàn)簡單的AOP,幫助大家為了更好的理解和學(xué)習(xí)AOP的思想,感興趣的朋友可以了解下
    2020-08-08
  • Java 中的垃圾回收機(jī)制詳解

    Java 中的垃圾回收機(jī)制詳解

    這篇文章主要為大家詳細(xì)介紹了Java垃圾回收機(jī)制的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Spring實(shí)現(xiàn)默認(rèn)標(biāo)簽解析流程

    Spring實(shí)現(xiàn)默認(rèn)標(biāo)簽解析流程

    這篇文章主要為大家詳細(xì)介紹了Spring實(shí)現(xiàn)默認(rèn)標(biāo)簽解析流程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java 實(shí)現(xiàn)分布式服務(wù)的調(diào)用鏈跟蹤

    Java 實(shí)現(xiàn)分布式服務(wù)的調(diào)用鏈跟蹤

    分布式服務(wù)中完成某一個(gè)業(yè)務(wù)動(dòng)作,需要服務(wù)之間的相互協(xié)作才能完成,在這一次動(dòng)作引起的多服務(wù)的聯(lián)動(dòng)我們需要用1個(gè)唯一標(biāo)識(shí)關(guān)聯(lián)起來,關(guān)聯(lián)起來就是調(diào)用鏈的跟蹤。本文介紹了Java 實(shí)現(xiàn)分布式服務(wù)的調(diào)用鏈跟蹤的步驟
    2021-06-06
  • Mybatis查不到數(shù)據(jù)查詢返回Null問題

    Mybatis查不到數(shù)據(jù)查詢返回Null問題

    mybatis突然查不到數(shù)據(jù),查詢返回的都是Null,但是 select count(*) from xxx查詢數(shù)量,返回卻是正常的。好多朋友遇到這樣的問題不知所措,下面小編通過本教程簡單給大家說明下
    2016-08-08
  • Java中的SPI機(jī)制使用解析

    Java中的SPI機(jī)制使用解析

    這篇文章主要介紹了Java中的SPI機(jī)制使用解析,SPI意思是"服務(wù)提供者的接口",專門提供給服務(wù)提供者或者擴(kuò)展框架功能的開發(fā)者去使用的接口,SPI 將服務(wù)接口和服務(wù)實(shí)現(xiàn)分離開來,將服務(wù)調(diào)用方和服務(wù)實(shí)現(xiàn)方進(jìn)行解耦,需要的朋友可以參考下
    2023-10-10
  • 第一次編寫Java流布局圖形界面

    第一次編寫Java流布局圖形界面

    這篇文章主要為大家詳細(xì)介紹了第一次編寫Java流布局圖形界面的相關(guān)代碼,感興趣的小伙伴們可以參考一下
    2016-08-08
  • 詳解Mybatis分頁插件 - 示例代碼

    詳解Mybatis分頁插件 - 示例代碼

    這篇文章主要介紹了詳解Mybatis分頁插件 - 示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧。
    2016-12-12
  • Java實(shí)現(xiàn)對一行英文進(jìn)行單詞提取功能示例

    Java實(shí)現(xiàn)對一行英文進(jìn)行單詞提取功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)對一行英文進(jìn)行單詞提取功能,結(jié)合實(shí)例形式分析了java基于StringTokenizer類進(jìn)行字符串分割的相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Spring?Security權(quán)限想要細(xì)化到按鈕實(shí)現(xiàn)示例

    Spring?Security權(quán)限想要細(xì)化到按鈕實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Spring?Security權(quán)限想要細(xì)化到按鈕實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評論