天天看點

多線程學習筆記——第一篇(線程)建立多線程第一種方法多線程原理記憶體圖解建立多線程的第二種方法Thread和Runnable的差別匿名内部類方式實作線程的建立

建立多線程第一種方法

建立多線程程式的第一種方式:建立Thread類的子類

java.lang.Thread類:是描述線程的類,我們想要實作多線程程式,就必須繼承Thread類

實作步驟:

1.建立一個Thread類的子類

2.在Thread類的子類中重寫Thread類中的run方法,設定線程任務(開啟線程要做什麼?)
    
    3.建立Thread類的子類對象
    
    4.調用Thread類中的方法start方法,開啟新的線程,執行run方法
    
         void start() 使該線程開始執行;Java 虛拟機調用該線程的 run 方法。
         
         結果是兩個線程并發地運作;目前線程(main線程)和另一個線程(建立的新線程,執行其 run 方法)。
         
         多次啟動一個線程是非法的。特别是當線程已經結束執行後,不能再重新啟動。
         
java程式屬于搶占式排程,那個線程的優先級高,那個線程優先執行;同一個優先級,随機選擇一個執行
           

代碼示範

main方法

public class Demo01Thread {
    public static void main(String[] args) {
        //3.建立Thread類的子類對象
        MyThread mt = new MyThread();
        //4.調用Thread類中的方法start方法,開啟新的線程,執行run方法
        mt.start();

        for (int i = 0; i <20 ; i++) {
            System.out.println("main:"+i);
        }
    }
}
           

MyThread類

//1.建立一個Thread類的子類
public class MyThread extends Thread{
    //2.在Thread類的子類中重寫Thread類中的run方法,設定線程任務(開啟線程要做什麼?)
    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            System.out.println("run:"+i);
        }
    }
}

           

多線程原理

多線程學習筆記——第一篇(線程)建立多線程第一種方法多線程原理記憶體圖解建立多線程的第二種方法Thread和Runnable的差別匿名内部類方式實作線程的建立

記憶體圖解

多線程學習筆記——第一篇(線程)建立多線程第一種方法多線程原理記憶體圖解建立多線程的第二種方法Thread和Runnable的差別匿名内部類方式實作線程的建立

執行mt.start就開辟一個新棧,cpu就可以有可以有多個選擇,多個程序互不影響

多線程學習筆記——第一篇(線程)建立多線程第一種方法多線程原理記憶體圖解建立多線程的第二種方法Thread和Runnable的差別匿名内部類方式實作線程的建立

建立多線程的第二種方法

采用 java.lang.Runnable 也是非常常見的一種,我們隻需要重寫run方法即可。

步驟如下:

  1. 定義Runnable接口的實作類,并重寫該接口的run()方法,該run()方法的方法體同樣是該線程的線程執行體。
  2. 建立Runnable實作類的執行個體,并以此執行個體作為Thread的target來建立Thread對象,該Thread對象才是真正 的線程對象。
  3. 調用線程對象的start()方法來啟動線程。
public class MyRunnable implements Runnable{
 @Override public void run() 
 { for (int i = 0; i < 20; i++) {
  System.out.println(Thread.currentThread().getName()+" "+i); } } }
  public class Demo {
   public static void main(String[] args) { 
  //建立自定義類對象 線程任務對象 
  MyRunnable mr = new MyRunnable();
   //建立線程對象 
   Thread t = new Thread(mr, "小強"); 
   t.start(); 
   for (int i = 0; i < 20; i++) 
   { System.out.println("旺财 " + i);
    } } }
           

通過實作Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程式的一個執行目标。所有的多線程 代碼都在run方法裡面。Thread類實際上也是實作了Runnable接口的類。 在啟動的多線程的時候,需要先通過Thread類的構造方法Thread(Runnable target) 構造出對象,然後調用Thread 對象的start()方法來運作多線程代碼。 實際上所有的多線程代碼都是通過運作Thread的start()方法來運作的。是以,不管是繼承Thread類還是實作 Runnable接口來實作多線程,最終還是通過Thread的對象的API來控制線程的,熟悉Thread類的API是進行多線程 程式設計的基礎

Thread和Runnable的差別

如果一個類繼承Thread,則不适合資源共享。但是如果實作了Runable接口的話,則很容易的實作資源共享。

總結: 實作Runnable接口比繼承Thread類所具有的優勢:

  1. 适合多個相同的程式代碼的線程去共享同一個資源。
  2. 可以避免java中的單繼承的局限性。
  3. 增加程式的健壯性,實作解耦操作,代碼可以被多個線程共享,代碼和線程獨立。
  4. 線程池隻能放入實作Runable或Callable類線程,不能直接放入繼承Thread的類

擴充:在java中,每次程式運作至少啟動2個線程。一個是main線程,一個是垃圾收集線程。因為每當使用 java指令執行一個類的時候,實際上都會啟動一個JVM,每一個JVM其實在就是在作業系統中啟動了一個程序。

匿名内部類方式實作線程的建立

使用線程的内匿名内部類方式,可以友善的實作每個線程執行不同的線程任務操作。 使用匿名内部類的方式實作Runnable接口,重新Runnable接口中的run方法:

package 一.線程;
/*
    匿名内部類方式實作線程的建立

    匿名:沒有名字
    内部類:寫在其他類内部的類

    匿名内部類作用:簡化代碼
        把子類繼承父類,重寫父類的方法,建立子類對象合一步完成
        把實作類實作類接口,重寫接口中的方法,建立實作類對象合成一步完成
    匿名内部類的最終産物:子類/實作類對象,而這個類沒有名字

    格式:
        new 父類/接口(){
            重複父類/接口中的方法
        };
 */
public class 匿名内部類方式實作多線程的建立 {
    public static void main(String[] args) {
        //線程的父類是Thread
        //new MyThread().start();
        
         new Thread(){
             @Override
             public void run() {
                 for (int i = 0; i < 20; i++) {
                     System.out.println(Thread.currentThread().getName()+"-->"+"黑馬");
                 }
             }
         }.start();

         //線程的接口Runnable
        //Runable r = new RunnableImpl
       Runnable r = new RunableImpl(){
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"高高高");
                }
            }
        };
         //開啟多線程
        new Thread(r).start();
         
         //簡化接口的方式 直接在r裡面加一堆
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"黑馬");
                }
            }
        }).start();


    }
}