多線程 --- 多線程編程

在寫代碼的時候,可以使用多進程進行并發編程(在Java中,不太推薦,很多很多關于進程相關的API,在Java標準庫中,都沒有提供),也可以使用多線程進行并發編程(系統提供了多線程編程的API,Java標準庫,已經將這些API封裝了,在代碼中可以直接使用)。

目錄

創建線程

方法1 繼承Thread類

方法2: 實現Runnable接口,重寫run方法

方法3. 繼承Thread,重寫run,但是使用匿名內部類

方法4. 實現Runnable,重寫 run,匿名內部類

方法5. 使用 lambda 表達式(常用)

完!


創建線程

方法1 繼承Thread類

繼承Thread來創建一個線程類

細節補充:

? ? ? ? 1. 第一行代碼: class MyThread extends Thread 中,繼承的Thread這個類,好像可以直接使用,并不像Scanner,ArrayList,Random一樣需要導包,這是為什么呢?

? ? ? ? 答:Java標準庫中,有一個特殊的包,java.lang包,這個包中包含了Thread類,且這個lang包是Java自動引入的。

? ? ? ? 2.自己創建的類MyThread中,類前面沒有public,這是怎么回事?前面能不能寫public?

? ? ? ? 答:一個 .java文件中,只能有一個public的類。 一個類前面如果沒有范圍限定符,那就默認是包級作用域,就是只能在當前包中被其他類使用。

? ? ? ? 3.怎么理解run方法是線程的入口方法?

? ? ? ? 答:此處的run方法,并不需要程序員來手動的進行調用,該方法會在線程創建好之后,一個合適的時機,被JVM自動的調用執行。就類似于,main方法,是一個java進程的入口方法。一個進程中,至少會有一個線程,這個進程中的第一個線程,也就稱為”主線程“。main方法,也就是主線程的入口方法。

補充:這種風格的函數,稱之為”回調函數“(callback)

在Java數據結構中,優先級隊列PriorityQueue,在使用的時候,必須要給對象實現一個比較的接口,才能進行使用。

回調函數 :作為參數傳遞給另一個函數,在該函數內部的某個特定時刻被調用執行的函數。其核心特點是函數的調用時機由其他代碼控制run方法的函數的調用時機由其他代碼(這里是 JVM)控制

? ? ? ? 4.run方法上面的 @Override 是什么意思?

? ? ? ? 答:方法重寫。本質上:是讓程序員能夠對現有的類,進行擴展。我們要搞一個線程,肯定是要讓這個線程執行一些代碼的,Thread類本身會帶有一個run方法。但很明顯,標準庫自帶的run方法,是不知道我們的具體需求的,業務要求是什么樣?必須要手動的進行指定,Override就是針對原有的Thread進行擴展(把一些能夠復用的,進行了重用,把需要擴展的,進行擴展)。Thread這個API中,會有很多的屬性方法,大部分內容直接復用即可,把需要擴展的內容,進行擴展即可。

? ? ? ? 那如果沒有@Override這個注解,貌似也可以實現方法重寫呀。為啥還要寫這個注解呢?語法中有很多的機制,是方便讓編譯器,對我們的代碼進行自動檢查的。(人是非常不靠譜的!!!機器是較為靠譜的!!!)(就比如fina限定符,限定一個變量不能再被修改,就是方便讓編譯器為我們進行自動檢查的)

? ? ? ? 5.一般來說,實例化的時候都是方式2。

? ? ? ? ?6.什么是操作系統的”內核“?

? ? ? ? 答:操作系統中,最核心部分的功能模塊(管理硬件,給軟件提供穩定的運行環境)

? ? ? ? 操作系統大致可以分為內核空間(內核態)和用戶空間(用戶態),平時運行的普通的應用程序,網易云音樂,idea,qq等等,都是運行在用戶態的。但是,這些應用程序,有時候,需要針對一些系統提供的硬件資源來進行操作。這些操作,都不是應用程序直接操作的,就是需要調用操作系統提供的API,進一步在內核中完成這樣的操作

? ? ? ? 為啥還要分出用戶態和內核態?

? ? ? ? 最主要的目的還是穩定。防止某些應用程序把硬件設備或者軟件資源給搞壞了。系統封裝了一些API,這些API都屬于是一些”合法“的操作,不會對硬件設備或者軟件資源有破壞,應用程序只能調用這些API來實現對應的功能,從而不至于對系統 / 硬件設備產生太大的危害。假如讓應用系統直接操作硬件,在極端條件下,代碼出現bug,會把硬件干壞。

? ? ? ? (就比如是銀行系統,辦事窗口里的工作人員,就是正經的經過培訓政審的安全人員,不會對銀行產生危害,用戶要辦理各種業務,就需要在辦事窗口前,給工作人員說清楚需求,由工作人員代辦)

具體解釋:每個線程都是一個獨立的執行流,每個線程都能夠獨立的去CPU上調度執行

如下圖代碼:

下面的死循環,是在 t 線程中執行的

而這個死循環,是在 main 線程中執行的

以之前的理解,如果一個代碼中,出現了兩個死循環,則肯定最多只能執行一個,另一個循環就進不去了。但我們把進程運行起來,可以看到,兩個循環,都在執行!這兩個線程,就是兩個獨立的執行流,也就解釋了我們最開始那句話:每個線程都是一個獨立的執行流,每個線程都能夠獨立的去CPU上調度執行

在調用start方法,創建線程之后,兵分兩路,一路,沿著main方法,繼續執行,打印hello main,另一路,進入到線程的run方法,打印hello thread。是相互獨立的,互不干擾的。

注意:

? ? ? ? 當有多個線程的時候,這些線程的執行的先后順序,是不確定的!!!(這一點,是因為操作系統內核中,有一個”調度器“模塊,這個模塊的實現方法,是一種類似于”隨機調度“的效果)

????????那隨即調度又是什么呢?

1. 一個線程,什么時候調度到CPU上去執行,時機是不確定的。

2. 一個線程,什么時候從 CPU上下來,給別人讓位,時機也是不確定的)

也稱為”搶占式執行“。

所以,每秒鐘到底是先執行 main 還是先執行thread,這是不一定的(隨機調度,搶占式執行)

主線程,在調用 strat 方法之后,就立即往下執行打印了,與此同時,內核就要通過剛才 API 構建出線程,并且執行run。由于創建線程本身也有開銷(雖然開銷比創建進程低,但也不是0).所以,在第一輪打印中,因為創建線程有一定的開銷影響,導致hello thread一般情況下 都比hello main略慢一籌。

我們剛剛,只是通過打印的方式,看到了兩個執行流,還可以通過一些第三方工具,更直觀的來查看多個線程的情況。 --> JDK中,有一個jconsole工具,該工具在JDK的bin文件夾中(該工具,只能列出java的進程,其他不是java的進程,無法進行分析)

注意,我們需要先把進程運行起來,然后再打開工具,找到對應的類名,然后進行鏈接

進入之后,選擇線程

main 對應的就是main方法的主線程

黃色框的,就是我們縮寫的代碼,創建的 t 線程(這個Thread - 0,1,2...是默認名稱 可以改)

剩下的線程,都是JVM自帶的線程,這些自帶的線程,要完成一些垃圾回收,監控統計各種指標....

點進具體的線程,就可以看到相關的調用棧(線程里當前執行到了那個方法的第幾行代碼,這個方法是如何如何一層調用過去的...)

這里這個線程的在不斷的運行的,點擊線程詳細情況的這個瞬間,就相當于咔嚓來一個閃照一樣,把這一瞬間的狀態展示到這里了。

這就是使用?jconsole 來檢測線程的方法

再回頭看我們的舉例代碼

我們在循環中加入了sleep方法,來降低這兩個死循環的速度(在C語言中,用的是Windows api中提供的Sleep函數,Windows.h),我們此處使用的sleep,是Java中封裝后的版本,屬于是Thread提供的靜態方法。

如果我們不進行 try - catch的話,該方法會編譯報錯,為什么必須需要拋出異常呢? --> 這個異常,意味著,在sleep(1000)的過程中,可能會被提前喚醒。(換句話說:sleep(1000)的作用是休眠1s,但在這休眠1s中,可能會被其他操作給提前喚醒,也就是沒休眠夠一秒,就被喚醒了,此處我們就應該在catch塊中 提出具體的解決方法,到底應該怎么做)

還有一點需要注意:

為什么在run方法中,解決sleep的異常只能是try - catch方法

但是在main方法中,可以是try - catch方法,也可以是在方法體上throws出異常

為什么呢?

原因很簡單,run方法中的sleep,如果加上throws的話,就修改了方法簽名了,這樣的話是無法構成”重寫“的,因為父類的run方法中,并沒有throws這個異常,子類重寫的時候,也就不能throws異常。

方法2: 實現Runnable接口,重寫run方法

1.實現Runnable接口

Runnable可以理解成”可執行的“,通過這個接口,就可以抽象表示出一段可以被其他實例來執行的代碼。

?2.創建Thread實例,調用Thread的構造方法時,將Runnable對象作為參數傳入。

Runnable接口,還需要搭配Thread類,才能真正在系統中創建出線程

3.調用start方法

上面這種寫法,其實是把 線程 和 要執行的任務 進行了解耦合了。

方法3. 繼承Thread,重寫run,但是使用匿名內部類

匿名內部類:是一種內部類,在一個類里面定義的類,其最大的特點是-->沒有名字,不能重復使用,用一次之后就找不到了。

解釋:

寫這個 { } 的意思是:定義一個類,與此同時,這個新的類,繼承自Thread。此處的 { } 中,可以定義子類的屬性和方法。此處最主要的目的就是重寫 run 方法。與此同時,這個代碼,還創建了子類的實例。且?t 指向的實例,并非是單純的Thread,而是 Thread的子類(但并不知道這個子類叫什么,因為是匿名的內部類)

方法4. 實現Runnable,重寫 run,匿名內部類

這種方法,在Thread構造方法的參數中,填寫了 Runnable 的匿名內部類的實例

方法5. 使用 lambda 表達式(常用)

在lambda表達式中, () 中是形參列表,這里可以帶參數,但因為線程的入口不需要參數,所以這里為空,() 的前面,應該還有一個函數名,此處作為匿名函數,就沒有名字了。

解釋:

在Java中,方法是不能脫離類單獨存在的,所以就不得不設置回調函數,從而多套了一層。但與此同時,java 語法也開了一個特殊的口子,就是 lambda 表達式,函數式接口,屬于是 lambda 背后的實現,相當于 java 在沒破壞原有的規則的基礎上,給了一個 lambda 一個合法性的解釋。

上述五種方法,都是等價的,可以互相轉換的,只不過是第五種 lambda 表達式的方法,更為簡潔一些,更加常用一些!

完!

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

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

相關文章

HTML~視頻音頻在網頁中不能自動播放

問題: autoplay是打開自動播放,但是發現加了關鍵詞還是沒有反應 原因: 現在瀏覽器禁止自動播放(特別是帶聲音的) 解決辦法: 可以添加muted 進行沒有聲音的自動播放

vue中上傳接口file表單提交二進制文件流

1.使用elementui上傳組件 要做一個選擇文件后&#xff0c;先不上傳&#xff0c;等最后點擊確定后&#xff0c;把file二進制流及附加參數一起提交上去。 首先使用elementui中的上傳組件&#xff0c;設置auto-uploadfalse&#xff0c;也就是選擇文件后不立刻上傳。 <el-uplo…

Flutter環境配置

配置環境變量 PUB_HOSTED_URLhttps://pub.flutter-io.cnFLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn 這個命令是用來配置 Flutter 的鏡像源地址&#xff0c;主要是為了解決在中國大陸地區訪問 Flutter 官方資源較慢的問題。 具體的操作如下&#xff1a; 右鍵點…

ngx_http_index_set_index

定義在 src\http\modules\ngx_http_index_module.c static char * ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {ngx_http_index_loc_conf_t *ilcf conf;ngx_str_t *value;ngx_uint_t i, n;ngx_http_inde…

數據庫的視圖有什么用?

數據庫的視圖&#xff08;View&#xff09;是一種虛擬表&#xff0c;它的內容由查詢定義&#xff0c;并不實際存儲數據&#xff0c;而是動態生成。視圖的主要作用如下&#xff1a; 1. 簡化復雜查詢 場景&#xff1a;當查詢涉及多表連接、復雜過濾或聚合操作時&#xff0c;SQL …

Ubuntu 24.04 安裝 Docker 詳細教程

前言 Docker 是目前最流行的容器化技術&#xff0c;它可以幫助開發者快速部署和運行應用程序。本文將詳細介紹在 Ubuntu 24.04 (Noble Numbat) 上安裝 Docker 的完整步驟&#xff0c;包括配置鏡像加速等實用技巧。 一、準備工作 1.1 系統要求 Ubuntu 24.04 LTS 具有 sudo 權…

鴻蒙進行視頻上傳,使用 request.uploadFile方法

一.拉起選擇器進行視頻選擇&#xff0c;并且創建文件名稱 async getPictureFromAlbum() {// 拉起相冊&#xff0c;選擇圖片let PhotoSelectOptions new photoAccessHelper.PhotoSelectOptions();PhotoSelectOptions.MIMEType photoAccessHelper.PhotoViewMIMETypes.VIDEO_TY…

C++ map容器總結

map基本概念 簡介&#xff1a; map中所有元素都是pair pair中第一個元素為key&#xff08;鍵值&#xff09;&#xff0c;起到索引作用&#xff0c;第二個元素為value&#xff08;實值&#xff09; 所有元素都會根據元素的鍵值自動排序 本質&#xff1a; map/multimap屬于關…

【Zookeeper搭建(跟練版)】Zookeeper分布式集群搭建

&#xff08;一&#xff09;克隆前的準備 1. 用 xftp 發送文件 2. 時間同步&#xff1a; sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 3. zookpeeper 安裝 部署 呼應開頭發送的壓縮包&#xff0c;解壓&#xff1a; cd ~ tar -zxvf zookeeper-3.4.6.tar.g…

Flutter項目之頁面實現以及路由fluro

目錄&#xff1a; 1、項目代碼結構2、頁面編寫以及路由配置main.dart(入口文件)page_content.dartindex.dart&#xff08;首頁&#xff09;application.dart&#xff08;啟動加載類&#xff09;pubspec.yaml&#xff08;依賴配置文件&#xff09;login.dart&#xff08;登錄頁&…

記錄Jmeter 利用BeanShell 腳本解析JSON字符串

下載org.json包(文檔說明) #下載地址 https://www.json.org/ # github 地址 https://github.com/stleary/JSON-java # api 文檔說明 https://resources.arcgis.com/en/help/arcobjects-java/api/arcobjects/com/esri/arcgis/server/json/JSONObject.htmlBeanShell腳本 import…

uniapp動態循環表單校驗失敗:初始值校驗

問題現象 &#x1f4a5; 在實現動態增減的單價輸入表單時&#xff08;基于uv-form組件&#xff09;&#xff0c;遇到以下詭異現象&#xff1a; <uv-input>的v-model綁定初始值為數字類型時&#xff0c;required規則失效 ?數字類型與字符串類型校驗表現不一致 &#x1…

UML 圖六種箭頭含義詳解:泛化、實現、依賴、關聯、聚合、組合

目錄 一、泛化&#xff08;Generalization&#xff09; 概念 表示方法 二、實現&#xff08;Realization&#xff09; 概念 表示方法 三、依賴&#xff08;Dependency&#xff09; 概念 表示方法 四、關聯&#xff08;Association&#xff09; 概念 表示方法 五、…

Android Logcat總結

文章目錄 Android Logcat總結日志格式過濾日志正向過濾反向過濾正則過濾日志等級 Android Logcat總結 日志格式 用法&#xff1a; Log.e("TAG", "hello") Log.i("TAG", "hello") Log.d("TAG", "hello")依次為&…

Unity UGUI - 六大基礎組件

目錄 一、Canvas上 1. Canvas&#xff1a;復制渲染子UI控件 2. ?Canvas Scaler?&#xff1a;畫布分辨率自適應 3. Graphics Raycaster&#xff1a;射線事件響應 4. ?Rect Transform?&#xff1a;UI位置錨點對齊 二、Event System上 5. Event System 6. Standalone …

基于Springboot的網上訂餐系統 【源碼】+【PPT】+【開題報告】+【論文】

網上訂餐系統是一個基于Java語言和Spring Boot框架開發的Web應用&#xff0c;旨在為用戶和管理員提供一個便捷的訂餐平臺。該系統通過簡化餐飲訂購和管理流程&#xff0c;為用戶提供快速、高效的在線訂餐體驗&#xff0c;同時也為管理員提供完善的后臺管理功能&#xff0c;幫助…

css 實現閃爍光標

要實現閃爍光標&#xff08;比如文本輸入框內常見的閃爍效果&#xff09;&#xff0c;可以使用 CSS 動畫。下面是一個簡單的方法&#xff1a; 代碼示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta n…

從JVM底層揭開Java方法重載與重寫的面紗:原理、區別與高頻面試題突破

&#x1f31f;引言&#xff1a;一場由方法調用引發的"血案" 2018年&#xff0c;某電商平臺在"雙十一"大促期間遭遇嚴重系統故障。 技術團隊排查發現&#xff0c;問題根源竟是一個繼承體系中的方法重寫未被正確處理&#xff0c;導致訂單金額計算出現指數級…

詳解Spark executor

在 Apache Spark 中&#xff0c;Executor&#xff08;執行器&#xff09; 是運行在集群工作節點&#xff08;Worker Node&#xff09;上的進程&#xff0c;負責執行具體的計算任務并管理數據。它是 Spark 分布式計算的核心組件之一&#xff0c;直接決定了任務的并行度和資源利用…

適配器模式及其典型應用

引言 適配器模式&#xff08;Adapter Pattern&#xff09;是一種結構型設計模式&#xff0c;它允許不兼容的接口協同工作。適配器模式通過創建一個適配器類來轉換一個類的接口&#xff0c;使其能夠與另一個類的接口兼容。這種模式在實際開發中非常有用&#xff0c;特別是在需要…