【JavaEE初階】認識線程、創建線程

1. 認識線程(Thread)

1.1 概念

1) 線程是什么

一個線程就是一個 "執行流". 每個線程之間都可以按照順序執行自己的代碼. 多個線程之間 "同時" 執行著多份代碼.

舉例:

還是回到我們之前的銀?的例?中。之前我們主要描述的是個?業務,即?個?完全處理??的業務。我們進?步設想如下場景:
?家公司要去銀?辦理業務,既要進?財務轉賬,?要進?福利發放,還得進?繳社保。
如果只有張三?個會計就會忙不過來,耗費的時間特別?。為了讓業務更快的辦理好,張三?找來兩位同事李四、王五?起來幫助他,三個?分別負責?個事情,分別申請?個號碼進?排隊,?此就有了三個執?流共同完成任務,但本質上他們都是為了辦理?家公司的業務。 此時,我們就把這種情況稱為多線程,將?個?任務分解成不同?任務,交給不同執?流就分別排隊執?。其中李四、王五都是張三叫來的,所以張三?般被稱為主線程(Main Thread)。

2) 為何要有線程 ?

首先,我們來說一下進程。在多任務操作系統中,希望系統能夠同時運行多個程序,這就引入了進程。如果是單任務的操作系統,就完全不涉及進程,也不需要管理(進程),更不需要調度。本質上說,進程是解決”并發編程“問題的,事實上,進程也可以很好地解決并發編程這樣的問題。

但是在一些特定的環境下,進程的表現不盡人意,比如,有些場景下,需要頻繁的創建和銷毀進程,舉例,最早的web開發,是使用C語言來編寫的服務器程序(基于一種CGI這樣的技術,其基于多進程的編程模式),服務器同一時刻會收到很多請求,針對每個請求,都會創建出一個進程,給這個請求提供一定的服務,返回對應的響應;一旦這個請求處理完了,此時這個進程就要銷毀了。如果請求很多,就意味著服務器要不停地創建進程、銷毀進程,此時使用多進程編程,系統的開銷就會很大(開銷主要體現在資源的申請和釋放上)。?

?先, "并發編程" 成為 "剛需"

  • 單核 CPU 的發展遇到了瓶頸. 要想提?算力, 就需要多核 CPU,而并發編程能更充分利?多核 CPU資源
  • 有些任務場景需要 "等待 IO", 為了讓等待 IO 的時間能夠去做?些其他的?作, 也需要?到并發編程
其次, 雖然多進程也能實現 并發編程, 但是線程比進程更輕量.
  • 創建線程?創建進程更快.
  • 銷毀線程?銷毀進程更快.
  • 調度線程?調度進程更快.

多線程并發編程,效率更高,尤其是對于java進程,是要啟動java虛擬機的,啟動java虛擬機開銷是更大的,搞多個java進程,就要多個java虛擬機。所以,java中不太去鼓勵多進程編程。

最后, 線程雖然比進程輕量, 但是人們還不滿足, 于是又有了 "線程池"(ThreadPool) 和 "協程"
(Coroutine)

3) 進程和線程的區別

  • 進程是包含線程的. 每個進程?少有?個線程存在,即主線程。
  • 進程和進程之間不共享內存空間. 同?個進程的線程之間共享同?個內存空間.
?如之前的多進程例?中,每個客戶來銀?辦理各?的業務,但他們之間的票據肯定是不想讓別?知道的,否則錢不就被其他?取?了么。?上?我們的公司業務中,張三、李四、王五雖然是不同的執?流,但因為辦理的都是?家公司的業務,所以票據是共享著的。這個就是多線程和多進程的最?區別。
  • 進程是系統分配資源的最小單位,線程是系統調度的最小單位。
  • ?個進程掛了?般不會影響到其他進程. 但是?個線程掛了, 可能把同進程內的其他線程?起帶?(整個進程崩潰).

另外注意:

  1. 同一個進程中的線程之間,可能會互相干擾,引起線程安全問題
  2. 線程也不是越多越好,要能夠合適,如果線程太多了,調度開銷可能會非常明顯?

?

4) Java 的線程 和 操作系統線程 的關系

線程是操作系統中的概念, 操作系統內核 實現了線程這樣的機制, 并且對用戶層提供了?些 API 供用戶使用(例如 Linux 的 pthread 庫)。
對于操作系統內核:
操作系統內核,是操作系統最核心部分的功能模塊(管理硬件、給軟件提供穩定的運行環境)。
操作系統 = 內核 + 配套的應用程序
這里用銀行為例來說明一下:
當你到銀行進行各種業務的辦理的時候,都是需要在辦事窗口前,給工作人員說清楚你的需求,由工作人員代辦。我們知道銀行中的辦事窗口內部和銀行大廳是分隔開的,你是進不去辦事窗口內部的, 這里的辦事窗口內部就相當于操作系統內核空間(內核態),你所在大廳則是用戶空間(用戶態)。?

為什么劃分出用戶態、內核態:

?最主要的目的,還是為了“穩定”。防止你的應用程序,把硬件設備或軟件資源給搞壞了。系統封裝了一些api,這些api都屬于是一些“合法”的操作,應用程序只能調用這些api,這樣就不至于對系統/硬件設備產生太大的危害。

假設讓應用程序直接操作硬件,可能極端情況下,代碼出現bug,就把硬件干燒了。

Java 標準庫中 Thread 類可以視為是對操作系統提供的 API 進行了進?步的抽象和封裝。

?1.2 第?個多線程程序

感受多線程程序和普通程序的區別:
  • 每個線程都是?個獨立的執行流
  • 多個線程之間是 "并發" 執行的
class MyThread2 extends Thread {//Thread類不用導包,屬于特殊的包java.long,該包默認自動導入@Overridepublic void run() {//run方法就是該線程的入口方法while (true) {System.out.println("hello run");try {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}
}
public class ThreadDemo2 {public static void main(String[] args) {//2、根據剛才的類,創建出具體的實例(線程實例,才是真正的線程)Thread t = new MyThread2();//3、調用Thread的start方法,才會真正調用系統api,在系統內核中創建出線程t.start();while (true) {System.out.println("hello main");try {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}
}

對于上述代碼,運行結果為兩個循環不停地同時輸出(驗證了多個線程之間是 "并發" 執行的)。

我們知道,若對于普通程序來說,當遇到一個無限循環,會停留在這個循環,不停的打印輸出,后續的代碼是執行不到的。然而這個多線程程序,兩個循環都執行到了,是因為每個線程都是?個獨立的執行流 。代碼中 t.start() ,即調用start()之后會創建一個新的線程,該線程進入到 run 方法,進行循環;而此時main線程,這個主線程會繼續自己的執行,執行后續代碼,也進行循環。

這里可以使用 jconsole 命令觀察線程

2. 創建線程的幾種方法

  • ?方法1 繼承 Thread 類

我們上面寫的第一個多線程程序就是用的該方法。

1、繼承 Thread 來創建?個線程類:
class MyThread extends Thread {@Overridepublic void run() {System.out.println("這?是線程運?的代碼");}
}
2、創建 MyThread 類的實例:
MyThread t = new MyThread();
3、調? start 方法啟動線程:
 t.start();  //調用start才會真正地創建線程
  • 方法2 實現 Runnable 接口

1、實現 Runnable 接口

class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("這?是線程運?的代碼");}
}

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

Thread t = new Thread(new MyRunnable());//或者另一種寫法
Runnable runnable = new MyRunnable();
Thread t = new Thread(runnable);

?3、調用start方法

t.start(); // 線程開始運?

該方法完整代碼示例:

class MyThread3 implements Runnable {@Overridepublic void run() {while (true) {System.out.println("hello runnable");try {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}
}
public class ThreadDemo3 {public static void main(String[] args) {
//        Runnable runnable = new MyThread3();
//        Thread t = new Thread(runnable);Thread t = new Thread(new MyThread3());t.start();while (true) {System.out.println("hello main");try {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}
}
對比上面兩種方法:
  • 繼承 Thread 類, 直接使用 this 就表示當前線程對象的引用.
  • 實現 Runnable 接口, this 表示的是 MyRunnable 的引用,需要使用Thread.currentThread()來表示當前線程對象

其他創建方法

  • 匿名內部類創建 Thread 子類對象

// 使?匿名類創建 Thread ?類對象
Thread t1 = new Thread() {@Overridepublic void run() {System.out.println("使?匿名類創建 Thread ?類對象");}
};
  • 匿名內部類創建 Runnable 子類對象?

// 使?匿名類創建 Runnable ?類對象
Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("使?匿名類創建 Runnable ?類對象");}
});
  • lambda 表達式創建 Runnable 子類對象?

// 使? lambda 表達式創建 Runnable ?類對象
Thread t3 = new Thread(() -> System.out.println("使?匿名類創建 Thread ?類對象"));
Thread t4 = new Thread(() -> {System.out.println("使?匿名類創建 Thread ?類對象");
});

3. 多線程的優勢-增加運行速度

可以觀察多線程在?些場合下是可以提高程序的整體運行效率的。
  • 使用 System.nanoTime() 可以記錄當前系統的 納秒 級時間戳.
  • serial 串行的完成?系列運算. concurrency 使用兩個線程并行的完成同樣的運算.
public class ThreadAdvantage {// 多線程并不?定就能提?速度,可以觀察,count 不同,實際的運?效果也是不同的private static final long count = 10_0000_0000;public static void main(String[] args) throws InterruptedException {// 使?并發?式concurrency();// 使?串??式serial();}private static void concurrency() throws InterruptedException {long begin = System.nanoTime();// 利??個線程計算 a 的值Thread thread = new Thread(new Runnable() {@Overridepublic void run() {int a = 0;for (long i = 0; i < count; i++) {a--;}}});thread.start();// 主線程內計算 b 的值int b = 0;for (long i = 0; i < count; i++) {b--;}// 等待 thread 線程運?結束thread.join();// 統計耗時long end = System.nanoTime();double ms = (end - begin) * 1.0 / 1000 / 1000;System.out.printf("并發: %f 毫秒%n", ms);}private static void serial() {// 全部在主線程內計算 a、b 的值long begin = System.nanoTime();int a = 0;for (long i = 0; i < count; i++) {a--;}int b = 0;for (long i = 0; i < count; i++) {b--;}long end = System.nanoTime();double ms = (end - begin) * 1.0 / 1000 / 1000;System.out.printf("串?: %f 毫秒%n", ms);}
}
并發: 399.651856 毫秒
串行: 720.616911 毫秒

?

該篇是對多線程的初步認識,接下來我會繼續更新多線程的相關內容,請多多關注!

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

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

相關文章

Python開源項目之人工智能老照片修復算法學習

文章目錄 前言項目環境搭建conda虛擬環境創建激活環境Pytorch安裝Synchronized-BatchNorm-PyTorch repository安裝Global目錄Synchronized-BatchNorm-PyTorch項目部署檢測預處理模型下載下載臉部增強模型文件下載依賴完整部署后項目結構 項目使用驗證一下總結關于Python技術儲備…

比較2個點的3種結構在不規則平面上的占比

2 2 2 1 2 2 2 2 2 1 2 2 2 2 2 1 2 2 3 3 3 x 3 3 2 2 2 1 2 2 2 2 2 1 2 2 在平面上有一個點x&#xff0c;再增加一個點,11的操作把平面分成了3部分2a1&#xff0c;2a2&#xff0c;2a3&#xff0c;3部分的比值是 2a1 2a2 2a3 5 25 …

spark中write算子和format算子詳解

在spark中&#xff0c;想要往數據庫或者某sink路徑里面寫數據&#xff0c;存到外部存儲系統&#xff0c;如文件系統、數據庫或數據倉庫&#xff0c;經常會用到write算子。 具體來說&#xff0c;write算子通常與DataFrame或Dataset API一起使用&#xff0c;用于將數據寫入持久化…

IDC最新報告,增速減緩+AI增勢,阿里云視頻云中國市場第一

國際權威數據公司IDC發布 《中國視頻云市場跟蹤&#xff08;2023 H1&#xff09;》報告 自2018年至今&#xff0c;阿里云持續保持 中國視頻云整體市場第一 整體市場占比達24.4% 01 第一之外&#xff0c;低谷之上 近期&#xff0c;國際權威數據公司IDC最新發布了《中國視頻…

做亞馬遜多久可以賺錢?做亞馬遜需要多少資金?——站斧瀏覽器

做亞馬遜需要時間、資金和全面的市場策略。創業者需要有耐心和決心&#xff0c;同時也要靈活應對市場變化。那么做亞馬遜多久可以賺錢,做亞馬遜需要多少資金。 做亞馬遜多久可以賺錢 首先&#xff0c;就像任何其他生意一樣&#xff0c;做亞馬遜需要時間和努力來建立起穩定的客…

怎么給圖片加水印?

怎么給圖片加水印&#xff1f;當代年輕人現在越來越愛在社交平臺中發表自己拍下來的一些趣事和美照&#xff0c;但是同樣的也會有人盜取他人圖片的方式來發布在自己的社交平臺中&#xff0c;而且沒有水印的照片一旦在網上流傳開來以后&#xff0c;很難追溯到它的來源&#xff0…

【MySQL】你知道索引查找起來為什么效率特別高嗎?

索引 前言正式開始磁盤、os、MySQL之間的IOMySQL與存儲扇區結論磁盤隨機訪問(Random Access)與連續訪問(Sequential Access)MySQL 與磁盤交互基本單位小總結簡單介紹一下內存池 談回MySQL簡單理解MySQL中的page為何IO交互基本單位是pagepage結構頁目錄單個page的頁目錄多個page…

井蓋位移傳感器生產廠家推薦,時刻感知井蓋

馬路上的井蓋雖然看似微不足道&#xff0c;但實際上對于行人的“腳下安全”起著至關重要的作用。這些井蓋下連接著供排水、燃氣、電力、供熱、通信等功能的管路和線路&#xff0c;是城市生命線運行的重要保障。因此保持井蓋狀態正常、明確管理責任是確保車輛和行人安全通行的重…

CART算法解密:從原理到Python實現

本文深入探討了CART&#xff08;分類與回歸樹&#xff09;算法的核心原理、實現方法以及應用場景。文章首先介紹了決策樹的基礎知識&#xff0c;然后詳細解析了CART算法的工作機制&#xff0c;包括特征選擇和樹的構建。接著&#xff0c;通過Python和PyTorch的實例代碼展示了CAR…

livox 半固體激光雷達 gazebo 仿真 | 更換仿真中mid360雷達外形

livox 半固體激光雷達 gazebo 仿真 | 更換仿真中mid360雷達外形 livox 半固體激光雷達 gazebo 仿真 | 更換仿真中mid360雷達外形livox 介紹更換仿真中mid360雷達外形 livox 半固體激光雷達 gazebo 仿真 | 更換仿真中mid360雷達外形 livox 介紹 覽沃科技有限公司&#xff08;L…

雙11后觀察:中國電商產業帶的數字新敘事

在電商平臺走過的第十五個雙11后&#xff0c;產業帶的數字化藍圖也更加完整。但在電商平臺與產業帶相互補足的背景下&#xff0c;一個更值得思考的問題是&#xff0c;隨著電商平臺的低價競爭愈演愈烈&#xff0c;產業帶上的供應鏈能力能否跟上&#xff1f; 作者|思杭 編輯|皮…

MEXC將上線UPCX(UPC)并開啟Launchpad活動

據官方公告&#xff0c;MEXC將上線UPCX項目的原生代幣UPC。上幣時間為2023-11-29 20:00 (UTC8)&#xff0c;開通UPC/USDT 交易對。 代幣名稱&#xff1a;UPCX (UPC) 總供應量&#xff1a;780,000,000 UPC 分配給 MEXC Launchpad 的代幣&#xff1a;100,000 UPC 代幣銷售形式&a…

【GCC】2:chatgpt:SendSideBandwidthEstimation

webrtc中SendSideBandwidthEstimation類的設計 The SendSideBandwidthEstimation class in WebRTC is a critical component in its video engine. It’s responsible for deciding the video traffic rate that can be sent without overloading the network and thus maintai…

分享5款經過時間驗證的精品軟件

? 今天來給大家推薦5款良心軟件,每款都是經過時間檢驗的精品,用起來讓你的工作效率提升飛快&#xff0c;各個都讓你覺得相見恨晚&#xff01; 1.文件夾隱藏工具——文件夾隱藏精靈 ? 文件夾隱藏精靈是一款可以隱藏你的文件夾和文件的工具&#xff0c;它可以讓你的隱私和重要…

NetApp ONTAP 數據安全解決方案,增強數據保護和安全性,同時提高數據治理與合規性

NetApp ONTAP 可幫助您創建智能、強大且值得信賴的存儲基礎架構&#xff0c;這種架構有助于降低成本、加快關鍵工作負載的運行速度、保護和保障混合云中的數據安全。 一、為什么選擇 NetApp ONTAP 數據安全解決方案&#xff1f; 全面保護企業最寶貴的資產 眾所周知&#xff…

Android:Google三方庫之Adjust集成詳細步驟

通過 Adjust 安卓 SDK&#xff0c;您可以在自己的安卓應用中跟蹤歸因、事件及更多數據。請按照本指南中說明的步驟操作&#xff0c;在應用內設置 Adjust SDK 1、添加依賴 //adjustimplementation("com.adjust.sdk:adjust-android:4.33.5")implementation("com.…

Aop面向切面實現開發日志收集打印一文輕松搞定,內附詳細圖文示例+源碼自取

目錄 介紹 動態代理 jdk動態代理 cglib動態代理 注解實現Aop 添加必須依賴 添加Atm類 (主業務邏輯代碼塊) 定義打印log方法(提取公共代碼邏輯塊) 啟用代理 切點表達式 Aop通知類型 前置通知(Before) 后置通知(After) 正常結束通知(AfterReturning) 異常結束通知…

樹莓派上使用Nginx通過內網穿透實現無公網IP訪問內網本地站點

前言 安裝 Nginx&#xff08;發音為“engine-x”&#xff09;可以將您的樹莓派變成一個強大的 Web 服務器&#xff0c;可以用于托管網站或 Web 應用程序。相比其他 Web 服務器&#xff0c;Nginx 的內存占用率非常低&#xff0c;可以在樹莓派等資源受限的設備上運行。同時結合c…

XTU OJ 1146 矩陣乘法學習筆記

原題 題目描述 給你兩個矩陣A(n*k),B(k*m),請求A*B。 輸入 第一行是一個整數K&#xff0c;表示樣例的個數。 每個樣例包含兩個矩陣A和B。 每個矩陣的第一行是兩個整數n,m,(1≤n,m≤10)表示矩陣的行和列 以后的n行&#xff0c;每行m個整數&#xff0c;每個整數的絕對值不超過…

如何讓大模型更好地完成知識圖譜推理?

? 論文標題&#xff1a; Making Large Language Models Perform Better in Knowledge Graph Completion 論文鏈接&#xff1a; https://arxiv.org/abs/2310.06671 代碼鏈接&#xff1a;GitHub - zjukg/KoPA: [Paper][Preprint 2023] Making Large Language Models Perform Be…