(轉)Java中的守護線程

Java的守護線程與非守護線程

守護線程與非守護線程

最近在看多線程的Timer章節,發現運用到了守護線程,感覺Java的基礎知識還是需要補充。

Java分為兩種線程:用戶線程和守護線程

所謂守護線程是指在程序運行的時候在后臺提供一種通用服務的線程,比如垃圾回收線程就是一個很稱職的守護者,并且這種線程并不屬于程序中不可或缺的部分。因 此,當所有的非守護線程結束時,程序也就終止了,同時會殺死進程中的所有守護線程。反過來說,只要任何非守護線程還在運行,程序就不會終止。

守護線程和用戶線程的沒啥本質的區別:唯一的不同之處就在于虛擬機的離開:如果用戶線程已經全部退出運行了,只剩下守護線程存在了,虛擬機也就退出了。 因為沒有了被守護者,守護線程也就沒有工作可做了,也就沒有繼續運行程序的必要了。

將線程轉換為守護線程可以通過調用Thread對象的setDaemon(true)方法來實現。在使用守護線程時需要注意一下幾點:

(1) thread.setDaemon(true)必須在thread.start()之前設置,否則會跑出一個IllegalThreadStateException異常。你不能把正在運行的常規線程設置為守護線程。

(2) 在Daemon線程中產生的新線程也是Daemon的。

(3) 守護線程應該永遠不去訪問固有資源,如文件、數據庫,因為它會在任何時候甚至在一個操作的中間發生中斷。

Timer代碼示例:

import java.util.Date;
import java.util.TimerTask;
public class MyTask extends TimerTask { @Override public void run() { System.out.println("任務執行了,時間為:"+new Date()); }

主函數

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;public class Test1 {
public static void main(String[] args){ System.out.println("當前時間:"+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); } }

運行結果:

    當前時間:Sat Jun 03 11:47:40 CST 2017 任務執行了,時間為:Sat Jun 03 11:47:50 CST 2017

任務雖然運行完了,但進程還未銷毀,呈紅色狀態,為什么會出現這種情況呢?

可以看一下Timer的源碼

public Timer() {this("Timer-" + serialNumber());
}
public Timer(String name) { thread.setName(name); thread.start(); }

可以看出每創建一個Timer就是啟動一個新的線程,那么啟動的線程不是守護線程,所以一直運行。將新創建的的Timer改成守護線程,更改如上的代碼:

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
public class Test1 {
public static void main(String[] args){ System.out.println("當前時間:"+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); } }

運行結果如下:

當前時間:Sat Jun 03 11:47:40 CST 2017

守護線程中產生的線程也是守護線程

如下示例:

public class Daemon implements Runnable { private Thread[] t = new Thread[10]; @Override 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(); } } }

類DaemonSpawn:

public class DaemonSpawn implements Runnable { @Override public void run() { while (true) { Thread.yield(); } } }

主函數:

import java.util.concurrent.TimeUnit;
public class Test1 { public static void main(String[] args) throws InterruptedException { Thread d = new Thread(new Daemon()); d.setDaemon(true); //必須在啟動線程前調用 d.start(); System.out.println("d.isDaemon() = " + d.isDaemon() + "."); TimeUnit.SECONDS.sleep(1); } }

運行結果如圖:

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. Process finished with exit code 0

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

public void sleep(long timeout) throws InterruptedException { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); Thread.sleep(ms, ns); } }

其實就是對Thread.sleep()的封裝,提供了可讀性更好的線程暫停操作
注釋后代碼運行如下:

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.

以上結果也說明了如果用戶線程全部退出了,只剩下守護線程存在了,虛擬機也就退出了。

標簽:?Java多線程

轉載于:https://www.cnblogs.com/panxuejun/p/10197723.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387673.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387673.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387673.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue項目中對axios的全局封裝

項目中接口會很多&#xff0c;個人喜歡創建api文件對請求統一管理1.新建api文件夾&#xff0c;文件夾下創建 axios.js&#xff0c;login.js2. axios.jsimport axios from axiosimport router from ../router //引入路由是為了做重定向&#xff0c;比如沒有登錄過期定向到登錄頁…

輪廓檢測

輪廓&#xff08;Contours&#xff09;&#xff0c;指的是有相同顏色或者密度&#xff0c;連接所有連續點的一條曲線。檢測輪廓的工作對形狀分析和物體檢測與識別都非常有用。 在輪廓檢測之前&#xff0c;首先要對圖片進行二值化或者Canny邊緣檢測。在OpenCV中&#xff0c;尋找…

【大數據】阿里云大數據助理工程師認證(ACA)課程

阿里云大數據助理工程師認證&#xff08;Alibaba Cloud Certified Associate&#xff0c;ACA&#xff09; 是面向使用阿里云大數據產品的專業技術認證&#xff0c;主要涉及阿里云的大數據計算、存儲、開發平臺&#xff0c;數據應用類的基礎產品。是對學員掌握阿里云大數據產品技…

WebGL——osg框架學習一

從今天開始&#xff0c;我們開始正式的學習osg框架&#xff0c;今天我們學習的是osg的渲染模塊&#xff0c;我們來看一下代碼結構。 所有DrawXXX的js模塊都是渲染的模塊&#xff0c;我們逐一來簡單介紹一下&#xff0c;第一個Drawable.js&#xff0c;這個模塊是描述可繪制對象的…

EmguCV 一些基本操作

一、先是在程序中圖像的導入&#xff0c;我是根據圖像路徑實現&#xff0c;其中path是string類型&#xff0c;是圖像路徑。 IntPtr imgCvInvoke.cvLoadImage(path, Emgu.CV.CvEnum.LOAD_IMAGE_TYPE.CV_LOAD_IMAGE_ANYCOLOR); 二、圖像灰度化處理&#xff0c;先創建一幅尺寸大小…

Java字符串分割

java中字符串的分割函數&#xff0c;split("你想要分割的字符", 你想要最多分割為多少段&#xff0c;正整數&#xff09; 注意事項&#xff1a; 1.分割特殊字符考慮轉義字符的使用。如&#xff1a; . \ | 2.第二個參數&#xff1a; 無&#xff1a; 不傳默認分割全部…

OpenCV人臉識別的原理 .

在之前講到的人臉測試后&#xff0c;提取出人臉來&#xff0c;并且保存下來&#xff0c;以供訓練或識別是用&#xff0c;提取人臉的代碼如下&#xff1a; [html] view plaincopy print?void GetImageRect(IplImage* orgImage, CvRect rectInImage, IplImage* imgRect,double s…

說一下SEO和SEM到底有哪些區別?

開場白免了&#xff0c;我們直接說與主題相關的。 SEO和SEM到底有什么區別&#xff1f; SEO和SEM到底有什么區別 我們先理解字面意思&#xff1a; SEO&#xff08;Search Engine Optimization&#xff09;&#xff1a;漢譯為搜索引擎優化。 SEM&#xff08;Search Engine Marke…

django模型的繼承

很多時候&#xff0c;我們都不是從‘一窮二白’開始編寫模型的&#xff0c;有時候可以從第三方庫中繼承&#xff0c;有時候可以從以前的代碼中繼承&#xff0c;甚至現寫一個模型用于被其它模型繼承。這樣做的好處&#xff0c;我就不贅述了&#xff0c;每個學習Django的人都非常…

SpringBoot部署項目到Docker倉庫

SpringBoot部署項目到Docker倉庫1.開啟遠程控制端口Centos7開啟方式&#xff1a; vim /lib/systemd/system/docker.service找到ExecStart行 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock 重啟docker 啟動 systemctl start docker守護進程…

人臉識別經典方法

這篇文章是擼主要介紹人臉識別經典方法的第一篇&#xff0c;后續會有其他方法更新。特征臉方法基本是將人臉識別推向真正可用的第一種方法&#xff0c;了解一下還是很有必要的。特征臉用到的理論基礎PCA在另一篇博客里&#xff1a;特征臉(Eigenface)理論基礎-PCA(主成分分析法)…

Jquery常用正則驗證

常用校驗的正則表達式var rulesConfig { /** * str.replace(/^\s|\s$/g, ) 解析&#xff1a; str&#xff1a;要替換的字符串 \s : 表示 space &#xff0c;空格 &#xff1a; 一個或多個 ^&#xff1a; 開始&#xff0c;^\s&#xff0c;以空格開始 $&#xff1a; 結束&#x…

svm參數說明

svm參數說明---------------------- 如果你要輸出類的概率&#xff0c;一定要有-b參數 svm-train training_set_file model_file svm-predict test_file model_fileoutput_file 自動腳本&#xff1a;Python easy.py train_data test_data 自動選擇最優參數&#xff0c;自動進行…

poj-3667(線段樹區間合并)

題目鏈接&#xff1a;傳送門 參考文章&#xff1a;傳送門 思路&#xff1a;線段樹區間合并問題&#xff0c;每次查詢到滿足線段樹的區間最左值&#xff0c;然后更新線段樹。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; co…

面試題編程題11-python 生成隨機數

隨機整數&#xff1a; random.randint(a,b), [a,b] random.randrange(a,b,step) [a,b) 隨機實數 random.random()返回0 到1 之間的浮點數轉載于:https://www.cnblogs.com/feihujiushiwo/p/10922454.html

車牌識別之顏色選取

車牌定位是車牌識別中第一步&#xff0c;也是最重要的一步。 由于中國車牌種類多樣&#xff0c;顏色不一&#xff0c; 再加上車牌經常有污損&#xff0c;以及車牌周圍干擾因素太多&#xff0c;都成為了車牌定位的難點。 這里首先使用最簡單算法來描述車牌定位&#xff0c;以及他…

Python - 排序( 插入, 冒泡, 快速, 二分 )

插入排序 算法分析 兩次循環, 大循環對隊列中的每一個元素拿出來作為小循環的裁定對象 小循環對堆當前循環對象在有序隊列中尋找插入的位置 性能參數 空間復雜度  O(1) 時間復雜度  O(n^2) 詳細代碼解讀 import randomdef func(l):# 外層循環: 對應遍歷所有的無序數據for i…

[EmguCV|C#]使用CvInvoke自己繪製色彩直方圖-直方圖(Hitsogram)系列(4)

2014-02-0610325 0C# 檢舉文章 過年結束了&#xff0c;雖然還是學生所以其實還有兩個禮拜的假期&#xff0c;不過為了不讓自己發慌&#xff0c;趁著假期多利用充實自己&#xff0c;所以提早回到開工狀態&#xff0c;而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 …

G.點我

鏈接&#xff1a;https://ac.nowcoder.com/acm/contest/903/G 題意&#xff1a; X腿與隊友到河北省來參加2019河北省大學生程序設計競賽&#xff0c;然而這場比賽的題目難度實在是太高了。比賽開始一個小時后&#xff0c;X腿仍然沒有做出一個題。這時候&#xff0c;X腿驚訝的發…

輪廓的查找、表達、繪制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)

前言 輪廓是構成任何一個形狀的邊界或外形線。前面講了如何根據色彩及色彩的分布&#xff08;直方圖對比和模板匹配&#xff09;來進行匹配&#xff0c;現在我們來看看如何利用物體的輪廓。包括以下內容&#xff1a;輪廓的查找、表達方式、組織方式、繪制、特性、匹配。 查…