# Java 線程教程
> 原文: [https://javabeginnerstutorial.com/core-java-tutorial/java-thread-tutorial/](https://javabeginnerstutorial.com/core-java-tutorial/java-thread-tutorial/)
可以以兩種方式使用線程術語
* 類`java.lang.Thread`的實例
* 執行線程
線程的*實例*是一個對象,與 Java 中的其他任何對象一樣,它包含在堆上生存和死亡的變量和方法。 但是*執行線程*是一個單獨的進程,具有其*棧*調用。 即使您沒有在程序中創建任何線程,一個線程也將在其中運行,然后`main()`方法將啟動該線程。
**注意**:如果是線程,大多數事情都是不可預測的。
## 線程類型
線程可以是兩種類型。
* 用戶線程
* 守護程序線程
這兩類線程之間的區別在于,JVM 僅在所有用戶線程完成時才退出應用。 JVM 并不關心守護線程的狀態。
## 線程定義
可以通過兩種方式定義線程
* 擴展`java.lang.Thread`類。
* 實現`Runnable`接口。
### 擴展 Java 線程類:
該類需要**擴展**,**線程**類并覆蓋`run()`方法。
```java
class MyThread extends Thread
{
public void run()
{
System.out.println("Important job running in MyThread");
}
}
```
但是這種方法的問題是類不能再擴展任何類。
> 線程的`run()`方法可以在類中重載。 但是,JVM 僅考慮`run()`方法(不帶參數)。 任何其他覆蓋的方法都需要顯式調用。
### 實現`Runnable`接口
該類需要實現`Runnable`接口,并且覆蓋`run()`方法。以這種方式創建線程使您可以靈活地擴展所需的任何類。
```java
class MyRunnable implements Runnable {
public void run() {
System.out.println("Important job running in MyRunnable");
} }
```
### 實例化線程:
每個執行線程都以`Thread`類的實例開始。 無論如何,都需要在創建執行線程之前創建線程對象。
兩種情況下創建線程對象均不同。 如果擴展了`Thread`類,則可以使用`new`關鍵字直接啟動類,因為它已經擴展了`Thread`類本身。
```java
MyThread t = new MyThread()
```
如果實現`Runnable`接口。 首先創建的可運行類需要實例化。
```java
MyRunnable r = new MyRunnable();
```
現在將此可運行對象傳遞給`Thread`。
```java
Thread t = new Thread(r);
```
如果使用無參構造器創建線程,則該線程將調用其自己的`run()`。 這是在第一種情況下發生的(擴展`Thread`類),但是在`Runnable`的情況下,需要知道實現了`Runnable`接口的類的`run`方法需要被調用,而不是`Thread`類的`run()`。 因此,我們需要將該類作為參數傳遞給`Thread`。 單個可運行實例可以傳遞給多個`Thread`對象。
```java
public class TestThreads {
public static void main (String [] args) {
MyRunnable r = new MyRunnable();
Thread foo = new Thread(r);
Thread bar = new Thread(r);
Thread bat = new Thread(r);
}}
```
將相同的目標分配給多個線程意味著多個執行線程將運行同一作業(并且同一作業將執行多次)。
> `Thread`類本身實現了`Runnable`。 (畢竟,它有一個我們要覆蓋的`run()`方法。)這意味著您可以將`Thread`傳遞給另一個`Thread`的構造器。
## `Thread`類中的重載構造器:
```java
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(String name)
```
到目前為止,我們已經創建了一個`Thread`對象,并且它知道以`run()`方法的形式做什么。 但是到目前為止,它仍然是一個對象。 它沒有調用棧。 換句話說,執行線程尚未啟動。 僅當在線程上調用`start()`方法時,線程對象才會具有其棧。
到目前為止,線程具有兩種狀態。
* 新狀態(已創建線程對象,但未調用`Start`方法)
* 可運行(活動)狀態(調用啟動方法)
> 直接從 Java 代碼調用`run()`方法意味著您正在調用方法,并且不會創建棧。
當線程處于可運行狀態時,表示已創建線程,但尚未執行該線程的`run`方法,并且該線程正在等待輪到他。 選定線程后,線程的`run`方法將執行,該狀態稱為運行狀態。
**線程調度器**:
線程調度器是 JVM 的一部分,它決定在任何給定的時間應該運行哪個線程,并使線程退出運行狀態 。 調度器可以選擇任何處于可運行狀態的線程作為唯一正在運行的線程。 如果線程不處于可運行狀態,則不能將其選擇為當前正在運行的線程。 某種可能在某種程度上影響調度器的方法(**注**:我們無法控制線程調度器的行為)
**這些方法來自線程類**
```java
* public static void sleep(long millis) throws InterruptedException
* public static void yield()
* public final void join() throws InterruptedException
* public final void setPriority(int newPriority)
```
**`Object`類中的方法。**
```java
* public final void wait() throws InterruptedException
* public final void notify()
* public final void notifyAll()
```
到目前為止,我們遇到了線程的三種狀態
* 新建
* 可運行的
* 正在運行
線程還有更多狀態,線程將無法運行。
* 等待/阻止/睡眠
* 死亡
當線程的`run`方法完成執行時,該線程處于死亡狀態。
`sleep()`:`sleep()`方法是`Thread`類的靜態方法。 (它仍然必須乞求成為當前正在運行的線程)。 由于它僅在當前是靜態方法,因此運行`Thread`將進入睡眠狀態。 語法為:`Thread.sleep()`
**`yield()`**:`yield`方法與`Thread`的優先級相關。 這也是一個靜態方法,因此它僅適用于當前正在運行的線程。 調度器確保如果線程進入可運行狀態,并且其優先級高于池中的任何線程,并且具有比當前正在運行的線程更高的優先級,則優先級較低的運行線程通常會被撞回可運行狀態,然后將選擇優先級最高的線程來運行。 在任何給定時間,當前正在運行的線程通常不會具有低于池中任何線程的優先級。 `yield()`應該做的是使當前正在運行的線程回到可運行狀態,以允許具有相同優先級的其他線程輪流使用。
**`Join()`**:`Join`是一種非靜態方法。 它使一個線程“連接到另一線程的末端”。 如果將線程 B 連接線程 A,則直到線程 A 完成,線程 B 才會啟動。
**語法**:
```java
Thread t = new Thread();
t.start();
t.join();
```
接收當前正在運行的線程,并將其連接到`t`引用的線程的末尾
線程可以離開運行狀態并返回到`Runnable`狀態的其他幾種方法。 運行方法完成對`wait()`的調用
**同步**:與鎖一起使用。 鎖有兩種類型。
**靜態鎖定**
**非靜態鎖定**
> 每個對象只有一個鎖。 一旦線程獲得了對象的鎖,其他線程就無法進入給定對象的同步塊/方法。
+ 僅方法/塊可以同步,而不是變量或類。
+ 一個類可以同時具有同步/同步方法。
+ 即使一個線程獲得了給定對象的鎖,線程也可以訪問同步塊。
+ 如果線程進入睡眠狀態,則它將擁有其擁有的所有鎖。 一個線程可以同時具有不同對象的鎖。
**語法**:
```java
class SyncTest {
public void doStuff() {
System.out.println("not synchronized");
synchronized(this) {
System.out.println("synchronized");
}}}
```
**同步靜態方法**:
靜態數據只有一個副本,因此每個類只需要一個鎖即可同步靜態方法,即整個類的鎖。 有這樣的鎖。 Java 中加載的每個類都有一個表示該類的`java.lang.Class`對應實例。 就是那個`java.lang.Class`實例,其鎖用于保護類的靜態方法。
**語法**:
```java
public static synchronized int getCount() {
return count;
}
```
`MyClass.class`事物稱為類字面值。 它告訴編譯器(誰告訴 JVM):去找我代表代表`MyClass`類的類實例。
> 在同一類中調用非靜態同步方法的線程只有在使用同一實例調用它們時才會彼此阻塞。 由于每個實例只有一個鎖。 在同一類中調用靜態同步方法的線程將始終相互阻塞,因為每個類只有一個鎖。
靜態同步方法和非靜態同步方法不會相互阻塞。 由于他們需要為其他事物鎖定(對象&類)
**注意**:`join()`,`sleep()`,`yield()`這些方法保持鎖定。 在等待釋放鎖定時。
## 備忘單
* 可以通過*擴展線程類*并覆蓋`run()`方法來創建線程。
* 也可以通過以下方法創建線程:*實現`Runnable`接口*,然后調用帶有`Runnable`參數的`Thread`構造器。
* `start()`方法只能在線程對象*上調用一次*。
* 一旦在線程對象上調用`start()`方法,它將成為*執行線程。* 在調用`start()`方法之前,它被稱為處于新狀態,并且不處于活動狀態。
* 不能保證啟動后線程執行的順序。
* 我們可以通過設置`Thread`優先級(1-10)來影響`Thread`執行的順序。
* 正在運行的線程可以通過`wait()`,`sleep`或`join()`調用進入阻塞/等待狀態。
* 正在運行的線程可能無法獲取同步代碼塊的鎖,因此可能會進入阻止/等待狀態。
* 死線程無法再次啟動。
- JavaBeginnersTutorial 中文系列教程
- Java 教程
- Java 教程 – 入門
- Java 的歷史
- Java 基礎知識:Java 入門
- jdk vs jre vs jvm
- public static void main(string args[])說明
- 面向初學者的 Java 類和對象教程
- Java 構造器
- 使用 Eclipse 編寫 Hello World 程序
- 執行順序
- Java 中的訪問修飾符
- Java 中的非訪問修飾符
- Java 中的數據類型
- Java 中的算術運算符
- Java 語句初學者教程
- 用 Java 創建對象的不同方法
- 內部類
- 字符串構建器
- Java 字符串教程
- Java 教程 – 變量
- Java 中的變量
- Java 中的局部變量
- Java 中的實例變量
- Java 引用變量
- 變量遮蓋
- Java 教程 – 循環
- Java for循環
- Java 教程 – 異常
- Java 異常教程
- 異常處理 – try-with-resources語句
- Java 異常處理 – try catch塊
- Java 教程 – OOPS 概念
- Java 重載
- Java 方法覆蓋
- Java 接口
- 繼承
- Java 教程 – 關鍵字
- Java 中的this關鍵字
- Java static關鍵字
- Java 教程 – 集合
- Java 數組教程
- Java 集合
- Java 集合迭代器
- Java Hashmap教程
- 鏈表
- Java 初學者List集合教程
- Java 初學者的Map集合教程
- Java 初學者的Set教程
- Java 初學者的SortedSet集合教程
- Java 初學者SortedMap集合教程
- Java 教程 – 序列化
- Java 序列化概念和示例
- Java 序列化概念和示例第二部分
- Java 瞬態與靜態變量
- serialVersionUID的用途是什么
- Java 教程 – 枚舉
- Java 枚舉(enum)
- Java 枚舉示例
- 核心 Java 教程 – 線程
- Java 線程教程
- Java 8 功能
- Java Lambda:初學者指南
- Lambda 表達式簡介
- Java 8 Lambda 列表foreach
- Java 8 Lambda 映射foreach
- Java 9
- Java 9 功能
- Java 10
- Java 10 獨特功能
- 核心 Java 教程 – 高級主題
- Java 虛擬機基礎
- Java 類加載器
- Java 開發人員必須知道..
- Selenium 教程
- 1 什么是 Selenium?
- 2 為什么要進行自動化測試?
- 3 Selenium 的歷史
- 4 Selenium 工具套件
- 5 Selenium 工具支持的瀏覽器和平臺
- 6 Selenium 工具:爭霸
- 7A Selenium IDE – 簡介,優點和局限性
- 7B Selenium IDE – Selenium IDE 和 Firebug 安裝
- 7C Selenium IDE – 突破表面:初探
- 7D Selenium IDE – 了解您的 IDE 功能
- 7E Selenium IDE – 了解您的 IDE 功能(續)。
- 7F Selenium IDE – 命令,目標和值
- 7G Selenium IDE – 記錄和運行測試用例
- 7H Selenium IDE – Selenium 命令一覽
- 7I Selenium IDE – 設置超時,斷點,起點
- 7J Selenium IDE – 調試
- 7K Selenium IDE – 定位元素(按 ID,名稱,鏈接文本)
- 7L Selenium IDE – 定位元素(續)
- 7M Selenium IDE – 斷言和驗證
- 7N Selenium IDE – 利用 Firebug 的優勢
- 7O Selenium IDE – 以所需的語言導出測試用例
- 7P Selenium IDE – 其他功能
- 7Q Selenium IDE – 快速瀏覽插件
- 7Q Selenium IDE – 暫停和反射
- 8 給新手的驚喜
- 9A WebDriver – 架構及其工作方式
- 9B WebDriver – 在 Eclipse 中設置
- 9C WebDriver – 啟動 Firefox 的第一個測試腳本
- 9D WebDriver – 執行測試
- 9E WebDriver – 用于啟動其他瀏覽器的代碼示例
- 9F WebDriver – JUnit 環境設置
- 9G WebDriver – 在 JUnit4 中運行 WebDriver 測試
- 9H WebDriver – 隱式等待
- 9I WebDriver – 顯式等待
- 9J WebDriver – 定位元素:第 1 部分(按 ID,名稱,標簽名稱)
- 9K WebDriver – 定位元素:第 2 部分(按className,linkText,partialLinkText)
- 9L WebDriver – 定位元素:第 3a 部分(按cssSelector定位)
- 9M WebDriver – 定位元素:第 3b 部分(cssSelector續)
- 9N WebDriver – 定位元素:第 4a 部分(通過 xpath)
- 9O WebDriver – 定位元素:第 4b 部分(XPath 續)
- 9P WebDriver – 節省時間的捷徑:定位器驗證
- 9Q WebDriver – 處理驗證碼
- 9R WebDriver – 斷言和驗證
- 9S WebDriver – 處理文本框和圖像
- 9T WebDriver – 處理單選按鈕和復選框
- 9U WebDriver – 通過兩種方式選擇項目(下拉菜單和多項選擇)
- 9V WebDriver – 以兩種方式處理表
- 9W WebDriver – 遍歷表元素
- 9X WebDriver – 處理警報/彈出框
- 9Y WebDriver – 處理多個窗口
- 9Z WebDriver – 最大化窗口
- 9AA WebDriver – 執行 JavaScript 代碼
- 9AB WebDriver – 使用動作類
- 9AC WebDriver – 無法輕松定位元素? 繼續閱讀...
- 10A 高級 WebDriver – 使用 Apache ANT
- 10B 高級 WebDriver – 生成 JUnit 報告
- 10C 高級 WebDriver – JUnit 報表自定義
- 10D 高級 WebDriver – JUnit 報告自定義續
- 10E 高級 WebDriver – 生成 PDF 報告
- 10F 高級 WebDriver – 截屏
- 10G 高級 WebDriver – 將屏幕截圖保存到 Word 文檔
- 10H 高級 WebDriver – 發送帶有附件的電子郵件
- 10I 高級 WebDriver – 使用屬性文件
- 10J 高級 WebDriver – 使用 POI 從 excel 讀取數據
- 10K 高級 WebDriver – 使用 Log4j 第 1 部分
- 10L 高級 WebDriver – 使用 Log4j 第 2 部分
- 10M 高級 WebDriver – 以無頭模式運行測試
- Vue 教程
- 1 使用 Vue.js 的 Hello World
- 2 模板語法和反應式的初探
- 3 Vue 指令簡介
- 4 Vue Devtools 設置
- 5 數據綁定第 1 部分(文本,原始 HTML,JavaScript 表達式)
- 6 數據綁定第 2 部分(屬性)
- 7 條件渲染第 1 部分(v-if,v-else,v-else-if)
- 8 條件渲染第 2 部分(v-if和v-show)
- 9 渲染列表第 1 部分(遍歷數組)
- 10 渲染列表第 2 部分(遍歷對象)
- 11 監聽 DOM 事件和事件修飾符
- 12 監聽鍵盤和鼠標事件
- 13 讓我們使用簡寫
- 14 使用v-model進行雙向數據綁定
- 15 表單輸入綁定
- 18 類綁定
- Python 教程
- Python 3 簡介
- Python 基礎知識 - 又稱 Hello World 以及如何實現
- 如何在 Windows 中安裝 python
- 適用于 Windows,Mac,Linux 的 Python 設置
- Python 數字和字符串
- Python 列表
- Python 集
- Python 字典
- Python 條件語句
- Python 循環
- Python 函數
- 面向對象編程(OOP)
- Python 中的面向對象編程
- Python 3 中的異常處理
- Python 3:猜數字
- Python 3:猜數字 – 回顧
- Python 生成器
- Hibernate 教程
- Hibernate 框架基礎
- Hibernate 4 入門教程
- Hibernate 4 注解配置
- Hibernate 4 的實體關系
- Hibernate 4 中的實體繼承模型
- Hibernate 4 查詢語言
- Hibernate 4 數據庫配置
- Hibernate 4 批處理
- Hibernate 4 緩存
- Hibernate 4 審計
- Hibernate 4 的并發控制
- Hibernate 4 的多租戶
- Hibernate 4 連接池
- Hibernate 自舉