認識多線程中start和run方法的區別?

来源:https://www.cnblogs.com/zhaosq/archive/2019/04/12/10564698.html
-Advertisement-
Play Games

一、認識多線程中的 start() 和 run() 1。start(): 先來看看Java API中對於該方法的介紹: 使該線程開始執行;Java 虛擬機調用該線程的 run 方法。 結果是兩個線程併發地運行;當前線程(從調用返回給 start 方法)和另一個線程(執行其 run 方法)。 多次啟動 ...


一、認識多線程中的 start() 和 run()

1。start():

    先來看看Java API中對於該方法的介紹:

     使該線程開始執行;Java 虛擬機調用該線程的 run 方法。

     結果是兩個線程併發地運行;當前線程(從調用返回給 start 方法)和另一個線程(執行其 run 方法)。

     多次啟動一個線程是非法的。特別是當線程已經結束執行後,不能再重新啟動。

用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體中的代碼執行完畢而直接繼續執行後續的代碼。通過調用Thread類的 start()方法來啟動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這裡的run()方法 稱為線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。

2。run():

同樣先看看Java API中對該方法的介紹:

      如果該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作並返回。

    Thread 的子類應該重寫該方法。

run()方法只是類的一個普通方法而已,如果直接調用Run方法,程式中依然只有主線程這一個線程,其程式執行路徑還是只有一條,還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下麵的代碼,這樣就沒有達到寫線程的目的。

3。總結:

調用start方法方可啟動線程,而run方法只是thread類中的一個普通方法調用,還是在主線程里執行。

二、代碼實例:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 public static void main(String args[]) {         Thread t = new Thread() {             public void run() {                 pong();             }         };         t.start();         System.out.print("ping");     }       static void pong() {         System.out.print("pang");     }

輸出結果: pingpang

 

 

1 2 3 4 5 6 7 8 9 10 11 12 13 public static void main(String args[]) {         Thread t = new Thread() {             public void run() {                 pong();             }         };         t.run();         System.out.print("ping");     }       static void pong() {         System.out.print("pang");     }

輸出結果:pongpang

 

通過以上兩個程式實例,可以很容易的區分出start()方法和run()方法的區別:

t.start(); 該行代碼相當於是啟動線程,

t.run(); 該行代碼相當於是使用t這個類中的run方法而已.

三、線程狀態說明:

線程狀態從大的方面來說,可歸結為:初始狀態可運行狀態不可運行狀態消亡狀態,具體可細分為上圖所示7個狀態,說明如下:

1)線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable介面,但不管怎樣,當我們new了Thread實例後,線程就進入了初始狀態

2)當該對象調用了start()方法,就進入可運行狀態

3)進入可運行狀態後,當該對象被操作系統選中,獲得CPU時間片就會進入運行狀態

4)進入運行狀態後涉及的情況就比較多,大致有如下情形: ﹒run()方法或main()方法結束後,線程就進入終止狀態; 當線程調用了自身的sleep()方法或其他線程的join()方法,就會進入阻塞狀態(該狀態雖停止當前線程,但並不釋放所占有的資源)。當sleep()結束或join()結束後,該線程進入可運行狀態,繼續等待OS分配時間片; 當線程剛進入可運行狀態(註意,還沒運行),發現將要調用的資源被鎖住(synchroniza,lock),將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池裡也許已經有了其他線程在等待獲取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記後,就轉入可運行狀態,等待OS分配 CPU時間片; 當線程調用wait()方法後會進入等待隊列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態後,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個線程,但我們由於不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒後會進入鎖池,等待獲取鎖標記。 當線程調用stop方法,即可使線程進入消亡狀態,但是由於stop方法是不安全的,不鼓勵使用,大家可以通過run方法里的條件變通實現線程的 stop。

 

安全終止線程的自定義方法:

public class SafeStopThread implements Runnable{

   //定義線程終止的開關
  private volatile boolean stop=false;//此變數必須加上volatile
  int a=0;
  @Override
  public void run() {
    // TODO Auto-generated method stub
    while(!stop){
      synchronized ("") {
      a++;
      try {
        Thread.sleep(100);
      } catch (Exception e) {
        // TODO: handle exception
      }
      a--;
      String tn=Thread.currentThread().getName();
      System.out.println(tn+":a="+a);

    }
   }
  //線程終止方法
   public void threadStop(){
      stop=true;
   }
   public static void main(String[] args) {
       SafeStopThread t=new SafeStopThread();
       Thread t1=new Thread(t);
       t1.start();
       for(int i=0;i<5;i++){
           new Thread(t).start();
       }
       t.threadStop();//改變終止線程的狀態
   }

 }

線程安全終止:https://blog.csdn.net/lexang1/article/details/49819347

好文轉載學習自:https://www.cnblogs.com/whyalwaysme/p/4495959.html


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

-Advertisement-
Play Games
更多相關文章
  • 因為是Node伺服器端的,怎樣實現前臺和後臺請求以及回應 URL(由什麼組成的 ),傳輸的內容:表單數據 文件數據 【圖片、壓縮包、各種尾碼文件】 URL的組成 URL由三部分組成: 協議類型 , 主機名 和 路徑及文件名 。通過URL可以指定的主要有以下幾種:http、ftp、gopher、tel ...
  • getter 和 setter: 1、ES5 里,屬性值可以用一個或兩個方法代替,這兩個方法就是 getter 和 setter,它們使用 get 和 set 進行定義而不是通過 function 2、由 getter 和 setter 定義的屬性稱作 “存取器屬性”,它不同於“數據屬性”,數據屬性 ...
  • 又有好長時間沒有寫博客了,今天想起來之前的那篇博客還沒有寫完,然後就開始接著寫,本來想把《高性能JavaScript》這本書的知識都羅列進來的,但是......太多了,哎,還是慢慢來,於是就打算分開來寫。 本人JavaScript水平並不是特別高,也只是把自己閱讀《高性能JavaScript》的部分 ...
  • 現在應用都是前後端分離,這也造成前端在調用介面時出現跨域問題,在控制台會這樣提示 ,如果有類似於此圖的提示,就已經表明你的介面調用出現了跨域問題,此文章是我對於vue跨域其中一種方式的一些經驗,如果錯誤,謝謝諒解!!! 首先對於vue跨域,我們可以用代理:在 config --> index.js里 ...
  • 這是我第一次寫博客,主要是記錄下自己解決問題的過程和知識的總結,如有不對的地方歡迎指出來! 需求:點擊btn,彈出modal顯示圖表(以折現圖為例) 這應該是很基本的需求也是很容易實現的,代碼和效果如下: 代碼解釋:setTem是一個方法,改變modal為true,預設為false ; chart- ...
  • 首先我們來瞭解一下什麼是文檔聲明: 文檔聲明就是文檔告訴游覽器該以什麼樣的標準去解析它。游覽器可以解析的文檔可不止html,還有xhtml,xml...當然在這裡我們並不需要知道xhtml、xml是什麼以及和html的區別,我們只需要知道,游覽器可以解析的文檔不止html ,所以文檔聲明是必須的,為 ...
  • 目的:將多個子系統的認證體系打通,實現一個入口多處使用 共用session最簡單最直接。以session存儲的值為用戶憑證,在用戶信息驗證用戶信息管理與業務應用分離的場景下會遇到單點登錄問題,適用體系簡單,考慮基於redis的session共用方案,將整個系統全局cookiesdomain設置於頂級 ...
  • 前言: Iterator翻譯過來就是迭代器的意思。在前面的工廠模式中就介紹過了iterator,不過當時介紹的是方法,現在從Iterator介面的設計來看,似乎又是一種設計模式,下麵我們就來講講迭代器模式到底是怎麼實現的。 一、定義 提供一種方法,順序訪問一個集合對象中的各個元素,而又不暴露該對象的 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...