Java線程的實現方式詳解(Java基礎)

你好我是辰兮,很高興你能來閱讀,本篇爲Java基礎之多線程的實現講解,基礎知識的講解,相關的更多,面試知識已經提前整理好文章可以閱讀學習,希望對初學者有幫助。



一、文章序言

創建線程的方式一致爲Java面試常見基礎問題,基礎學習中我們常用前兩種方式,下文帶大家用代碼案例進一步瞭解相關的知識。

在這裏插入圖片描述

  • 常用第二種接口實現,因爲實現接口的方式比繼承類的方式更靈活,也能減少程序之間的耦合度。

二、繼承Thread類

繼承自Thread類,Thread類是所有線程類的父類,實現了對線程的抽取和封裝

繼承Thread類創建並啓動多線程的步驟:

  • ①.定義一個類,繼承自Thread類,並重寫該類的run方法,該run方法的方法體就代表了線程需要完成的任務,因此,run方法的方法體被稱爲線程執行體
  • ②.創建Thread子類的對象,即創建了子線程
  • ③.用線程對象的start方法來啓動該線程

Demo先創建一個售票線程

package demo1;

public class SellTickets extends Thread {
    //共享數據
    static int count = 100;
    @Override
    public void run() {
        //循環售票
        while(count > 0) {
            count--;
            System.out.println(Thread.currentThread().getName() + "售出了一張票,剩餘" + count);
        }
    }
}

測試類

import demo1.SellTickets;

public class TheadDemo {

    public  static void main(String[] args) {
        //模擬四個售票員售票
        SellTickets s1 = new SellTickets();
        SellTickets s2 = new SellTickets();
        SellTickets s3 = new SellTickets();
       // System.out.println(s1.currentThread().getName());  //這個線程的名稱是main
        s1.start();
        s2.start();
        s3.start();

    }
}

在這裏插入圖片描述


三、實現Runnable接口

實現Runnable接口創建並啓動多線程的步驟:

  • a.定義一個Runnable接口的實現類,並重寫該接口中的run方法,該run方法的方法體同樣是該線程的線程執行 體
  • b.創建Runnable實現類的實例,並以此實例作爲Thread的target來創建Thread對象,該Thread對象纔是真正的線程對象
  • c.調用線程對象的start方法來啓動該線程

  • 繼續售票的案例 應該是繼承implement接口,爲了簡潔我寫一個裏面了
package demo1;

public class SellTickets {
    static int count = 100;
    static Runnable r = new Runnable() {
      @Override
      public void run() {
          while(count > 0) {
              count--;
              System.out.println(Thread.currentThread().getName() + "售出了 一張票,剩餘" + count);
          }
      }
  };

    public static void main(String[] args) {
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        Thread t3 = new Thread(r);
        t1.start();
        t2.start();
        t3.start();
      }
}

在這裏插入圖片描述


四、兩種實現方式的比較

①實現Runnable接口的方式

a.線程類只是實現了Runnable接口,還可以繼承其他類【一個類在實現接口的同時還可以繼承另外一個類】
b.可以多個線程共享同一個target對象,所以非常適合多個線程來處理同一份資源的情況
c.弊端:編程稍微複雜,不直觀,如果要訪問當前線程,必須使用Thread.currentThread()

② 繼承Thread類的方式

a.編寫簡單,如果要訪問當前線程,除了可以通過Thread.currentThread()方式之外,還可以使用 super關鍵字
b.弊端:因爲線程類已經繼承了Thread類,則不能再繼承其他類【單繼承】 實際上大多數的多線程應用都可以採用實現Runnable接口的方式來實現【推薦使用匿名內部類】java類是單知繼承的


五、調用start()與run()方法的區別

Thread thread = new Thread();
thread.start();

① - start()方法會新建一個線程,並且讓這個線程執行run()方法。

Thread thread = new Thread();
thread.run();

② - 調用run()也能正常執行。但是,卻不能新建一個線程,而是在當前線程中調用run()方法,只是作爲一個普通的方法調用。

我知道這樣表達有點抽象,所有我截圖了上述案例

在這裏插入圖片描述

在這裏插入圖片描述

建議:不要用run()來開啓新線程,它只會在當前線程中,串行執行run()方法中的代碼。


拓展一下源碼的學習只截取了部分

public synchronized void start() {

    private native void start0();

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }


}

在start方法裏調用了一次start0方法,這個方法是一個只聲明未定義的方法,並且使用了native關鍵字進行定義native指的是調用本機的原生系統函數。所以,調用start方法,會告訴JVM去分配本機系統的資源,才能實現多線程。


The best investment is to invest in yourself

在這裏插入圖片描述

2020.05.29 記錄辰兮的第70篇博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章