併發基礎之正確啟動多線程

来源:https://www.cnblogs.com/chen88/archive/2019/11/05/11802279.html
-Advertisement-
Play Games

start方法和run方法比較 很多人包括我自己也以前也認為run和start方法都可以啟動一個線程,並且兩者的功能都差不多,然後在學習的過程中認識到這是錯誤的,他們之間是 截然不同 的。先來看一段演示代碼: 輸出結果: 可以看到, 執行run方法的線程是主線程,而執行start方法的才是一個新的子 ...


start方法和run方法比較

很多人包括我自己也以前也認為run和start方法都可以啟動一個線程,並且兩者的功能都差不多,然後在學習的過程中認識到這是錯誤的,他們之間是截然不同的。先來看一段演示代碼:

/**
 * @author Chen
 * @Description start()和run()方法比較
 * @create 2019-11-05 22:01
 */
public class StartAndRunMethod {
    public static void main(String[] args) {
        //使用run方法
        Runnable runnable = ()-> System.out.println(Thread.currentThread().getName());
        runnable.run();

        //使用start方法
        new Thread(runnable).start();
    }
}

輸出結果:

main
Thread-0

可以看到,執行run方法的線程是主線程,而執行start方法的才是一個新的子線程。

start方法解讀

我們都知道start方法就是啟動一個新線程,其實真是情況是start方法執行過程中會涉及到兩個線程,一個是主線程,另一個是新的子線程,當調用start方法是,子線程並不會馬上啟動起來,子線程會獲取除了cpu以外的一些資源,進入就狀態,等待CPU的調用。至於什麼時候調用,這個就不是我們所能決定的了,而是線程調度器來決定的。所以有一些先運行start方法的線程可能會在比後調用start方法的線程啟動的慢。

當我們重覆調用兩次start方法會發生什麼?

會拋出一個異常IllegalThreadStateException(非法的線程狀態),其實線程一旦執行,就會進入runnable狀態,一旦執行完畢,就會進入結束狀態,不會在返回回去。

接下來我們在來仔細看看start(),瞭解一下它執行的過程中到底幹了什麼。

  public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

start()中,首先會檢查線程的狀態,判斷threadStatus是不是等於0,也就是判斷是不是一個新啟動的線程,這是執行兩次start()拋出異常的原因。(線上程剛剛被初始化的時候預設的狀態為0)

然後又做了一個加入線程組這個行為,然後又執行了個start0的native方法。

run方法解讀

其實run方法比較簡單,只有三行代碼:如果target也就是傳入的介面不為空,就執行重寫的run方法的內容,否則就執行傳入的run方法的內容。

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

所以當我們執行run方法的時候,它就會作為一個普通的方法,和我們自己寫的一樣,所以控制台列印出來的是一個主線程。

所以我們想啟動一個新線程不能直接調用run方法,而是應該調用start方法來間接調用run方法。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 2019-11-05-23:03:28 List集合: java.util.List 介面繼承自 Collection 介面,是單列集合的一個重要分支,習慣性地會將實現了List 介面的對象稱為List集合 特點: 1. 它是一個元素存取有序的集合。例如,存元素的順序是11、22、33。那麼集合中, ...
  • 1. 列表 1.1 列表的介紹 列表是python的基礎數據類型之⼀,其他編程語⾔也有類似的數據類型。比如JS中的數組, java中的數組等等。它是以[ ]括起來,每個元素⽤','隔開⽽且可以存放各種數據類型: lst = [1, '哈哈', "吼吼", [1,8,0,"百度"], ("我","叫" ...
  • 1. python介紹 1.1 python是什麼樣的語言 編程語⾔主要從以下⼏個⻆度為進⾏分類,編譯型和解釋型、靜態語⾔和動態語⾔、強類型定義語⾔和弱類型定義語⾔,我們先看編譯型語⾔和解釋型語⾔.稍後再說強類型和弱類型 編譯和解釋的區別是什麼? 編譯器是把源程式的每⼀條語句都編譯成機器語⾔,並保存 ...
  • 開發環境: Windows操作系統 開發工具:MyEclipse/Eclipse + JDK+ Tomcat + MySQL 資料庫 項目簡介: 系統前段頁面採用jsp + JavaScript + css的組合技術開發,其中JavaScript使用了jQuery和bootstrap框架,這兩個前段 ...
  • 1.緩存雪崩和緩存穿透問題 1.1緩存雪崩 簡介:緩存同一時間大面積的失效,所以,後面的請求都會落到資料庫上,造成資料庫短時間內承受大量請求而崩掉。 解決辦法:  事前:儘量保證整個 redis 集群的高可用性,發現機器宕機儘快補上。選擇合適的記憶體淘汰策略。  事中:本地 ehcache 緩存 ...
  • 一、基礎類介紹 1、工作簿類Workbook簡介: import xlwt class Workbook(object0): ''' 工作簿類,使用xlwt創建excel文件時,首先要實例化此類的對象 ''' def __init__(self, encoding='ascii', style_co ...
  • 在項目開發過程中經常遇到時間處理,但是你真的用對了嗎,理解阿裡巴巴開發手冊中禁用static修飾SimpleDateFormat嗎 通過閱讀本篇文章你將瞭解到: 為什麼需要LocalDate、LocalTime、LocalDateTime【java8新提供的類】 java8新的時間API的使用方式, ...
  • 1. 樂觀鎖 樂觀鎖顧名思義就是在操作時很樂觀,認為操作不會產生併發問題(不會有其他線程對數據進行修改),因此不會上鎖。但是在更新時會判斷其他線程在這之前有沒有對數據進行修改,一般會使用版本號機制或CAS(compare and swap)演算法實現。簡單理解:這裡的數據,別想太多,你儘管用,出問題了 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...