《Java 高并發》03 線程的生命周期

相關概念

進程是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。

一個進程是一個獨立的運行環境,它可以被看作一個程序或者一個應用。而線程是在進程中執行的一個任務。Java運行環境是一個包含了不同的類和程序的單一進程。線程可以被稱為輕量級進程。線程需要較少的資源來創建和駐留在進程中,并且可以共享進程中的資源。

多線程程序中,多個線程被并發的執行以提高程序的效率,CPU不會因為某個線程需要等待資源而進入空閑狀態。多個線程共享堆內存(heap memory),因此創建多個線程去執行一些任務會比創建多個進程更好。舉個例子,ServletsCGI 更好,是因為 Servlets 支持多線程而 CGI 不支持。

這里所謂的多個線程“同時”執行是人的感覺,實際上,是多個線程輪換執行。

線程調度器(Thread Scheduler)是一個操作系統服務,它負責為Runnable狀態的線程分配CPU時間。一旦我們創建一個線程并啟動它,它的執行便依賴于線程調度器的實現。

時間片(Time Slicing)是指將可用的CPU時間分配給可用的Runnable線程的過程。分配CPU時間可以基于線程優先級或者線程等待的時間。線程調度并不受到Java虛擬機控制,所以由應用程序來控制它是更好的選擇(也就是說不要讓你的程序依賴于線程的優先級)。

線程的生命周期(六種狀態)

public enum State {NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;
}
  • NEW:只存在于線程剛創建,未調用start之前。
MyThread myThread = new MyThread();System.out.println(myThread.getState());
  • RUNNABLE:正在 JVM 中執行,但是這個"執行",不一定是真的在運行, 也有可能是在等待CPU資源。所以,在網上,有人把這個狀態區分為READYRUNNING兩個,一個表示的start了,資源一到位隨時可以執行,另一個表示真正的執行中,這取決于操作系統處理器。
MyThread myThread = new MyThread();myThread.start();System.out.println(myThread.getState());
  • BLOCKED:線程等待獲取一個鎖,來繼續執行下一步的操作,比較經典的就是synchronized關鍵字,這個關鍵字修飾的代碼塊或者方法,均需要獲取到對應的鎖,在未獲取之前,其線程的狀態就一直未BLOCKED,如果線程長時間處于這種狀態下,我們就要當心是否會出現死鎖的情況。
public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();MyThread thread2 = new MyThread(lock);thread2.start();Thread.sleep(1000);//等一會再檢查狀態System.out.println(thread2.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {synchronized (lock) {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("done");}}
}
  • WAITING:等待狀態。進入這個狀態,一定是執行了如下的一些代碼,例如

    • Object.wait()
    • Thread.join()
    • LockSupport.park()

    當一個線程執行了Object.wait()的時候,它一定在等待另一個線程執行Object.notify()或者Object.notifyAll()。或者一個線程thread,其在主線程中被執行了thread.join()的時候,主線程即會等待該線程執行完成。當一個線程執行了LockSupport.park()的時候,其在等待執行LockSupport.unpark(thread)。當該線程處于這種等待的時候,其狀態即為WAITING。需要關注的是,這邊的等待是沒有時間限制的,當發現有這種狀態的線程的時候,若其長時間處于這種狀態,也需要關注下程序內部有無邏輯異常。

    LockSupport.park()

    public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();Thread.sleep(100);System.out.println(thread1.getState());LockSupport.unpark(thread1);Thread.sleep(100);System.out.println(thread1.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {LockSupport.park();}
    }

    Object.wait()

    public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();Thread.sleep(100);System.out.println(thread1.getState()); //這時候線程狀態應為WAITINGsynchronized (lock){lock.notify(); //notify通知wait的線程}Thread.sleep(100);System.out.println(thread1.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {synchronized (lock){try {lock.wait(); //wait并允許其他線程同步lock} catch (InterruptedException e) {e.printStackTrace();}}}
    }

    Thread.join()

    public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread1 thread1 = new MyThread1(lock);thread1.start();MyThread2 thread2 = new MyThread2(thread1);thread2.start();Thread.sleep(100);System.out.println(thread2.getState());}}class MyThread1 extends Thread {private byte[] lock = new byte[0];public MyThread1(byte[] lock) {this.lock = lock;}@Overridepublic void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}
    }class MyThread2 extends Thread {Thread thread;public MyThread2(Thread thread) {this.thread = thread;}@Overridepublic void run() {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}
    }
  • TIMED_WAITING:這個狀態和WAITING狀態的區別就是,這個狀態的等待是有一定時效的,即可以理解為WAITING狀態等待的時間是永久的,即必須等到某個條件符合才能繼續往下走,否則線程不會被喚醒。但是TIMED_WAITING,等待一段時間之后,會喚醒線程去重新獲取鎖。當執行如下代碼的時候,對應的線程會進入到TIMED_WAITING狀態。

    • Thread.sleep(long)
    • Object.wait(long)
    • Thread.join(long)
    • LockSupport.parkNanos()
    • LockSupport.parkUntil()
  • TERMINATED:這個狀態很好理解,即為線程執行結束之后的狀態

線程的狀態圖

?

image-20200814160913095

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

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

相關文章

OpenLayers3 online build

openlayers3使用了一個比較復雜的build工具,從github上下載下來的代碼中并沒有build之后的版本,要配置build環境又比較繁瑣,好在官方的example中提供了在線的版本,下面就是link: http://openlayers.org/en/v3.0.0/buil…

Mysql 必知必會(一)

文章案例所需的SQL文件,點擊下載 使用MySQL 進入mysql安裝目錄下的bin目錄: 連接Mysql:mysql -uroot -p123456;顯示Mysql下的所有數據庫:show databases;切換數據庫:use local;顯示數據庫下所有表名:show t…

design.js

//模塊式開發 var myNamespace (function () { var myPrivateVar 0;var myPrivateMethod function (foo) {console.log(foo); };return {myPublicVar : "foo",myPublicFunction : function (bar) {myPrivateVar;myPrivateMethod(bar);} }; })(); //原型模式 var…

Spring boot 整合dynamic實現多數據源

項目git地址:Jacob-dynamic 準備工作 # 創建數據庫db1 CREATE DATABASE db1CHARACTER SET utf8 COLLATE utf8_bin # 創建user表 CREATE TABLE user (id int(11) DEFAULT NULL,name varchar(255) DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8 # 添加數據 INSERT…

LInux 命令大全

開關機 reboot:重啟shutdown -h 0 或者init 0 :關機halt:關機poweroff:關機 文件的操作 ll:顯示文件夾詳細信息ls:顯示文件目錄mkdir fileName:創建目錄mkdir -p fileName/fileName:目錄cd file…

企業級業務系統開發實戰-序言

前些年一直在做微軟的解決方案實施與軟件開發的工作。在學習、項目實施、開發與管理的過程中學到了別人不少好的東西,也自身總結了大量的經驗,希望能夠通過一個系列來跟大家分享關于軟件開發方面的內容。 這個開發系列的由來是這樣的,兩年前作…

Could not autowire. No beans of 'JavaMailSender' type found..md

Could not autowire. No beans of JavaMailSender type found. 導入依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><version>2.1.5.RELEASE</version> </depe…

極客Web前端開發資源集錦

本周我們帶來的前端推薦包含當前熱門的bootstrap&#xff0c;html5&#xff0c;css3等技術內容和新聞話題&#xff0c;如果你還想近一步學習如何開發&#xff0c;還可以關注我們的極客課程庫&#xff0c;里面涵蓋了現代開發技術的‘學’與‘習’的全新功能。希望對大家有所幫助…

mahout學習筆記4

分析數據 有哪些數據 選用什么樣的推薦算法 Finding an effective recommender 各種算法組合測試 Tanimoto算法在與thresholdneighborhoold結合時值應該設置比較底&#xff0c;0.5已經是很高的相似度 可以重寫ItemSimilarity &#xff0c;把自己的功能放到里面 IDRescorer 可以…

使用 Spring Cloud 實現微服務系統

使用 Spring Cloud 實現微服務系統 準備工作&#xff1a;為了方便創建項目&#xff0c;以及各版本以來關系&#xff0c;此次創建項目使用 Spring Assistant插件。 創建單體服務中心項目 啟用服務端的服務注冊&#xff0c;發現功能 EnableEurekaServer SpringBootApplication pu…

HTML+CSS公司培訓(一)高手請飄過

隨著公司的轉向&#xff0c;從.net到webapp很多人無從適應。因此在公司進行一些簡單的培訓。同時把我微薄的經驗分享給大家&#xff0c;并且和大家一起學習進步。 對于HTML在正常的開發中我們其實用的標簽就是那么簡單的幾個&#xff08;是小編在項目開發中常用的一些&#xff…

【LeetCode】整數反轉

package leetcode.editor.cn;//給出一個 32 位的有符號整數&#xff0c;你需要將這個整數中每位上的數字進行反轉。 // // 示例 1: // // 輸入: 123 //輸出: 321 // // // 示例 2: // // 輸入: -123 //輸出: -321 // // // 示例 3: // // 輸入: 120 //輸出: 21 // // //…

sql 中實現打亂數據的排序

sql 中實現打亂數據的排序order by NEWID()就實現了數據的打亂 轉載于:https://www.cnblogs.com/yangjinwang/p/3998271.html

【LeetCode】兩數之和

package leetcode.editor.cn;//給定一個整數數組 nums 和一個目標值 target&#xff0c;請你在該數組中找出和為目標值的那 兩個 整數&#xff0c;并返回他們的數組下標。 // // 你可以假設每種輸入只會對應一個答案。但是&#xff0c;數組中同一個元素不能使用兩遍。 // // …

Docker學習筆記1 :鏡像制作

參考資源&#xff1a; http://blog.csdn.net/kongxx?viewmodecontents http://my.oschina.net/feedao/blog 運行環境win8.1 virtual box, 運行 centos6.4 64bit&#xff0c; 內網通過代理上網。 如下操作基本都在root下進行。 目的嘗試自己建立Docker鏡像 基礎工作1&#xf…

讓不帶www的域名跳轉到帶www的域名

域名不帶www和帶www不是同一碼事&#xff1a;前者稱作根域名&#xff0c;后者是前者的二級域名。長久以來&#xff0c;人們都習慣了訪問網站的時候帶上www&#xff0c;所以大多數站長朋友域名解析的時候都是帶www的和不帶www的一起解析。然而對于搜索引擎來說&#xff0c;還是會…

RestTemplate 發送 Https 請求調用

RestTemplate 發送 Https 請求調用 個人博客:https://jacob.org.cn import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.htt…

【LeetCode】回文數

個人博客:https://jacob.org.cn package leetcode.editor.cn;//判斷一個整數是否是回文數。回文數是指正序&#xff08;從左向右&#xff09;和倒序&#xff08;從右向左&#xff09;讀都是一樣的整數。 // // 示例 1: // // 輸入: 121 //輸出: true // // // 示例 2: // …

android 小工具:pc 上用 curl 命令打開手機瀏覽器,瀏覽指定網址

測試 API 時或其它情況經常需要在手機瀏覽器中輸入 url 一長串的 url 輸起來真是麻煩 AirDroid 很強大也不用數據線&#xff0c;但有時老斷開連接&#xff0c;不是很爽。發到手機 qq 吧還得手動粘貼 所以自己開發了一個小工具 pc 上用 curl 發一條命令&#xff0c;命令中輸入要…

cron 表達式詳解

cron表達式詳解 Cron表達式是一個字符串&#xff0c;字符串以5或6個空格隔開&#xff0c;分為6或7個域&#xff0c;每一個域代表一個含義&#xff0c;Cron有如下兩種語法格式&#xff1a; &#xff08;1&#xff09; Seconds Minutes Hours DayofMonth Month DayofWeek Year …