天天看點

黑馬程式員_日記11_多線程(一)

 ——- android教育訓練、java教育訓練、期待與您交流! ———-

一、概述

程序:是一個正在執行中的程式。

每一個程序執行都有一個執行順序。該順序是一個執行路徑,或者叫一個控制單元。

線程:就是程序中的一個獨立的控制單元。

線程在控制着程序的執行。

一個程序中至少有一個線程。

Java VM 啟動的時候會有一個程序java.exe.

該程序中至少一個線程負責java程式的執行。

而且這個線程運作的代碼存在于main方法中。

該線程稱之為主線程。

擴充:其實更細節說明jvm,jvm啟動不止一個線程,還有負責垃圾回收機制的線程。

二、建立線程

1,如何在自定義的代碼中,自定義一個線程呢?

通過對api的查找,java已經提供了對線程這類事物的描述。就Thread類。

建立線程的第一種方式:繼承Thread類。

步驟:

1,定義類繼承Thread。

2,複寫Thread類中的run方法。

目的:将自定義代碼存儲在run方法。讓線程運作。

3,調用線程的start方法,

該方法兩個作用:啟動線程,調用run方法。

下面通過一個練習來展示:

練習:建立兩個線程,和主線程交替運作。

步驟:

1、定義類繼承Thread

2、覆寫run方法(run方法中的内容就是線程執行的代碼)

3、調用start方法。start的作用有兩個:啟動線程并調用run方法。

1 源代碼之一

//定義類繼承Thread
class Demo1 extends Thread
{
    //覆寫Thread的run方法,規定線程執行的代碼
    public void run()
    {
        //用一個for循環列印數字,來辨別線程運作的狀态
        for(int i = 0; i<60;i++)
            System.out.println("Demo1Run:"+i);
    }
}

//定義類繼承Thread
class Demo2 extends Thread
{
    //覆寫Thread的run方法,規定線程執行的代碼
    public void run()
    {
        //用一個for循環列印數字,來辨別線程運作的狀态
        for(int i = 0; i<60;i++)
            System.out.println("Demo2Run:"+i);
    }
}

class ThreadDemo
{
    public static void main(String[] args)//主線程
    {
        //建立線程1
        Demo1 d1= new Demo1();
        //建立線程2
        Demo2 d2 = new Demo2();

        //線程1調用start方法,啟動線程,調用run方法
        d1.start();
        //線程2調用start方法,啟動線程,調用run方法
        d2.start();

        //用for循環列印數字,來辨別主線程運作的狀态
        for(int i = 0;i < 50; i++)
            System.out.println("MainRun:"+i);


    }
}
           

2 源代碼之二

上面那一段代碼程式的重複很多,下面精簡一下代碼

隻定義一個類來繼承Thread,重載構造函數.

class Demo extends Thread
{
    private String name;//定義私有字元串變量name用來區分不同線程對象

    Demo(String name)
    {
        this.name = name;
    }

    //覆寫Thread的run方法,規定線程執行的代碼
    public void run()
    {
        //用一個for循環列印數字,來辨別線程運作的狀态
        for(int i = 0; i<60;i++)
            System.out.println("Demo"+name+" is Run---"+i);
    }
}


class ThreadDemo
{
    public static void main(String[] args)//主線程
    {
        //建立線程1
        Demo d1= new Demo("1");
        //建立線程2
        Demo d2 = new Demo("2");

        //線程1調用start方法,啟動線程,調用run方法
        d1.start();
        //線程2調用start方法,啟動線程,調用run方法
        d2.start();

        //用for循環列印數字,來辨別主線程運作的狀态
        for(int i = 0;i < 50; i++)
            System.out.println("Main is Run---"+i);


    }
}
           

3 運作結果:

Main is Run—0

Demo2 is Run—0

Demo1 is Run—0

Demo2 is Run—1

Demo2 is Run—2

Main is Run—1

Main is Run—2

Demo2 is Run—3

Demo2 is Run—4

Demo1 is Run—1

Demo2 is Run—5

Main is Run—3

Main is Run—4

Demo2 is Run—6

Demo1 is Run—2

Demo2 is Run—7

Main is Run—5

Demo2 is Run—8

Demo1 is Run—3

Demo2 is Run—9

Main is Run—6

Demo2 is Run—10

Demo2 is Run—11

Demo1 is Run—4

Demo2 is Run—12

Main is Run—7

Demo2 is Run—13

Demo1 is Run—5

Demo1 is Run—6

Demo2 is Run—14

Demo2 is Run—15

Main is Run—8

Main is Run—9

Demo2 is Run—16

Demo1 is Run—7

Demo2 is Run—17

Main is Run—10

Demo2 is Run—18

Demo1 is Run—8

Demo2 is Run—19

Main is Run—11

Demo2 is Run—20

Demo1 is Run—9

Demo2 is Run—21

Main is Run—12

Demo2 is Run—22

Demo1 is Run—10

Demo2 is Run—23

Main is Run—13

Demo2 is Run—24

Demo1 is Run—11

Demo1 is Run—12

Demo2 is Run—25

Main is Run—14

Main is Run—15

Demo2 is Run—26

Demo1 is Run—13

Demo2 is Run—27

Main is Run—16

Demo2 is Run—28

Demo1 is Run—14

Demo2 is Run—29

Main is Run—17

Demo2 is Run—30

Demo2 is Run—31

Demo1 is Run—15

Demo2 is Run—32

Main is Run—18

Demo2 is Run—33

Demo1 is Run—16

Demo2 is Run—34

Main is Run—19

Demo2 is Run—35

Demo2 is Run—36

Demo1 is Run—17

Demo1 is Run—18

Demo2 is Run—37

Main is Run—20

Demo2 is Run—38

Demo1 is Run—19

Demo1 is Run—20

Demo1 is Run—21

Demo2 is Run—39

Demo2 is Run—40

Main is Run—21

Demo2 is Run—41

Demo1 is Run—22

Demo2 is Run—42

Main is Run—22

Demo2 is Run—43

Demo1 is Run—23

Demo2 is Run—44

Demo2 is Run—45

Demo2 is Run—46

Main is Run—23

Demo2 is Run—47

Demo1 is Run—24

Demo2 is Run—48

Main is Run—24

Demo2 is Run—49

Demo1 is Run—25

Demo2 is Run—50

Main is Run—25

Demo2 is Run—51

Demo1 is Run—26

Demo2 is Run—52

Main is Run—26

Demo2 is Run—53

Demo1 is Run—27

Demo2 is Run—54

Main is Run—27

Demo2 is Run—55

Demo1 is Run—28

Demo2 is Run—56

Main is Run—28

Demo2 is Run—57

Demo1 is Run—29

Demo2 is Run—58

Demo2 is Run—59

Main is Run—29

Demo1 is Run—30

Main is Run—30

Demo1 is Run—31

Main is Run—31

Demo1 is Run—32

Main is Run—32

Demo1 is Run—33

Main is Run—33

Demo1 is Run—34

Main is Run—34

Demo1 is Run—35

Main is Run—35

Demo1 is Run—36

Main is Run—36

Demo1 is Run—37

Main is Run—37

Demo1 is Run—38

Main is Run—38

Demo1 is Run—39

Main is Run—39

Main is Run—40

Demo1 is Run—40

Demo1 is Run—41

Main is Run—41

Demo1 is Run—42

Main is Run—42

Demo1 is Run—43

Main is Run—43

Demo1 is Run—44

Main is Run—44

Demo1 is Run—45

Main is Run—45

Demo1 is Run—46

Demo1 is Run—47

Main is Run—46

Main is Run—47

Main is Run—48

Main is Run—49

Demo1 is Run—48

Demo1 is Run—49

Demo1 is Run—50

Demo1 is Run—51

Demo1 is Run—52

Demo1 is Run—53

Demo1 is Run—54

Demo1 is Run—55

Demo1 is Run—56

Demo1 is Run—57

Demo1 is Run—58

Demo1 is Run—59

結果顯示:兩個線程和主線程在交替運作。

三、run方法和start方法的差別

下面通過具體程式運作來區分。

1 源代碼之一

//隻定義一個類來繼承Thread,重載構造函數
class Demo extends Thread
{
    private String name;//定義私有字元串變量name用來區分不同線程對象

    Demo(String name)
    {
        this.name = name;
    }

    //覆寫Thread的run方法,規定線程執行的代碼
    public void run()
    {
        //用一個for循環列印數字,來辨別線程運作的狀态
        for(int i = 0; i<60;i++)
            System.out.println("Demo"+name+" is Run---"+i);
    }
}


class ThreadDemo
{
    public static void main(String[] args)//主線程
    {
        //建立線程1
        Demo d1= new Demo("1");
        //建立線程2
        Demo d2 = new Demo("2");

        //線程1調用start方法,啟動線程,調用run方法
        d1.start();
        //線程2調用run方法,
        d2.run();

        //用for循環列印數字,來辨別主線程運作的狀态
        for(int i = 0;i < 50; i++)
            System.out.println("Main is Run---"+i);


    }
}
           

2 運作結果:

Demo2 is Run—0

Demo1 is Run—0

Demo2 is Run—1

Demo1 is Run—1

Demo1 is Run—2

Demo1 is Run—3

Demo1 is Run—4

Demo1 is Run—5

Demo1 is Run—6

Demo2 is Run—2

Demo2 is Run—3

Demo2 is Run—4

Demo2 is Run—5

Demo2 is Run—6

Demo2 is Run—7

Demo2 is Run—8

Demo2 is Run—9

Demo2 is Run—10

Demo2 is Run—11

Demo1 is Run—7

Demo1 is Run—8

Demo1 is Run—9

Demo1 is Run—10

Demo2 is Run—12

Demo1 is Run—11

Demo2 is Run—13

Demo1 is Run—12

Demo2 is Run—14

Demo1 is Run—13

Demo2 is Run—15

Demo1 is Run—14

Demo2 is Run—16

Demo1 is Run—15

Demo2 is Run—17

Demo2 is Run—18

Demo1 is Run—16

Demo1 is Run—17

Demo1 is Run—18

Demo1 is Run—19

Demo1 is Run—20

Demo1 is Run—21

Demo1 is Run—22

Demo1 is Run—23

Demo1 is Run—24

Demo1 is Run—25

Demo1 is Run—26

Demo1 is Run—27

Demo1 is Run—28

Demo1 is Run—29

Demo1 is Run—30

Demo1 is Run—31

Demo1 is Run—32

Demo1 is Run—33

Demo1 is Run—34

Demo1 is Run—35

Demo1 is Run—36

Demo1 is Run—37

Demo1 is Run—38

Demo1 is Run—39

Demo1 is Run—40

Demo1 is Run—41

Demo1 is Run—42

Demo1 is Run—43

Demo1 is Run—44

Demo1 is Run—45

Demo1 is Run—46

Demo1 is Run—47

Demo1 is Run—48

Demo2 is Run—19

Demo1 is Run—49

Demo1 is Run—50

Demo2 is Run—20

Demo1 is Run—51

Demo1 is Run—52

Demo1 is Run—53

Demo2 is Run—21

Demo1 is Run—54

Demo2 is Run—22

Demo2 is Run—23

Demo1 is Run—55

Demo1 is Run—56

Demo1 is Run—57

Demo1 is Run—58

Demo1 is Run—59

Demo2 is Run—24

Demo2 is Run—25

Demo2 is Run—26

Demo2 is Run—27

Demo2 is Run—28

Demo2 is Run—29

Demo2 is Run—30

Demo2 is Run—31

Demo2 is Run—32

Demo2 is Run—33

Demo2 is Run—34

Demo2 is Run—35

Demo2 is Run—36

Demo2 is Run—37

Demo2 is Run—38

Demo2 is Run—39

Demo2 is Run—40

Demo2 is Run—41

Demo2 is Run—42

Demo2 is Run—43

Demo2 is Run—44

Demo2 is Run—45

Demo2 is Run—46

Demo2 is Run—47

Demo2 is Run—48

Demo2 is Run—49

Demo2 is Run—50

Demo2 is Run—51

Demo2 is Run—52

Demo2 is Run—53

Demo2 is Run—54

Demo2 is Run—55

Demo2 is Run—56

Demo2 is Run—57

Demo2 is Run—58

Demo2 is Run—59

Main is Run—0

Main is Run—1

Main is Run—2

Main is Run—3

Main is Run—4

Main is Run—5

Main is Run—6

Main is Run—7

Main is Run—8

Main is Run—9

Main is Run—10

Main is Run—11

Main is Run—12

Main is Run—13

Main is Run—14

Main is Run—15

Main is Run—16

Main is Run—17

Main is Run—18

Main is Run—19

Main is Run—20

Main is Run—21

Main is Run—22

Main is Run—23

Main is Run—24

Main is Run—25

Main is Run—26

Main is Run—27

Main is Run—28

Main is Run—29

Main is Run—30

Main is Run—31

Main is Run—32

Main is Run—33

Main is Run—34

Main is Run—35

Main is Run—36

Main is Run—37

Main is Run—38

Main is Run—39

Main is Run—40

Main is Run—41

Main is Run—42

Main is Run—43

Main is Run—44

Main is Run—45

Main is Run—46

Main is Run—47

Main is Run—48

Main is Run—49

無論運作多少次,都會有一個特點:

隻有當Demo is Run列印完了,

Main is Run才會列印。

為什麼呢??

3 源代碼之二

再來看一個例子。

class Demo extends Thread
{
    private String name;//定義私有字元串變量name用來區分不同線程對象

    Demo(String name)
    {
        this.name = name;
    }

    //覆寫Thread的run方法,規定線程執行的代碼
    public void run()
    {
        //用一個for循環列印數字,來辨別線程運作的狀态
        for(int i = 0; i<60;i++)
            System.out.println("Demo"+name+" is Run---"+i);
    }
}


class ThreadDemo
{
    public static void main(String[] args)//主線程
    {
        //建立線程1
        Demo d1= new Demo("1");
        //建立線程2
        Demo d2 = new Demo("2");

        //線程1調用run方法
        d1.run();
        //線程2調用run方法,
        d2.run();

        //用for循環列印數字,來辨別主線程運作的狀态
        for(int i = 0;i < 50; i++)
            System.out.println("Main is Run---"+i);
    }
}
           

4 運作結果:

Demo1 is Run—0

Demo1 is Run—1

Demo1 is Run—2

Demo1 is Run—3

Demo1 is Run—4

Demo1 is Run—5

Demo1 is Run—6

Demo1 is Run—7

Demo1 is Run—8

Demo1 is Run—9

Demo1 is Run—10

Demo1 is Run—11

Demo1 is Run—12

Demo1 is Run—13

Demo1 is Run—14

Demo1 is Run—15

Demo1 is Run—16

Demo1 is Run—17

Demo1 is Run—18

Demo1 is Run—19

Demo1 is Run—20

Demo1 is Run—21

Demo1 is Run—22

Demo1 is Run—23

Demo1 is Run—24

Demo1 is Run—25

Demo1 is Run—26

Demo1 is Run—27

Demo1 is Run—28

Demo1 is Run—29

Demo1 is Run—30

Demo1 is Run—31

Demo1 is Run—32

Demo1 is Run—33

Demo1 is Run—34

Demo1 is Run—35

Demo1 is Run—36

Demo1 is Run—37

Demo1 is Run—38

Demo1 is Run—39

Demo1 is Run—40

Demo1 is Run—41

Demo1 is Run—42

Demo1 is Run—43

Demo1 is Run—44

Demo1 is Run—45

Demo1 is Run—46

Demo1 is Run—47

Demo1 is Run—48

Demo1 is Run—49

Demo1 is Run—50

Demo1 is Run—51

Demo1 is Run—52

Demo1 is Run—53

Demo1 is Run—54

Demo1 is Run—55

Demo1 is Run—56

Demo1 is Run—57

Demo1 is Run—58

Demo1 is Run—59

Demo2 is Run—0

Demo2 is Run—1

Demo2 is Run—2

Demo2 is Run—3

Demo2 is Run—4

Demo2 is Run—5

Demo2 is Run—6

Demo2 is Run—7

Demo2 is Run—8

Demo2 is Run—9

Demo2 is Run—10

Demo2 is Run—11

Demo2 is Run—12

Demo2 is Run—13

Demo2 is Run—14

Demo2 is Run—15

Demo2 is Run—16

Demo2 is Run—17

Demo2 is Run—18

Demo2 is Run—19

Demo2 is Run—20

Demo2 is Run—21

Demo2 is Run—22

Demo2 is Run—23

Demo2 is Run—24

Demo2 is Run—25

Demo2 is Run—26

Demo2 is Run—27

Demo2 is Run—28

Demo2 is Run—29

Demo2 is Run—30

Demo2 is Run—31

Demo2 is Run—32

Demo2 is Run—33

Demo2 is Run—34

Demo2 is Run—35

Demo2 is Run—36

Demo2 is Run—37

Demo2 is Run—38

Demo2 is Run—39

Demo2 is Run—40

Demo2 is Run—41

Demo2 is Run—42

Demo2 is Run—43

Demo2 is Run—44

Demo2 is Run—45

Demo2 is Run—46

Demo2 is Run—47

Demo2 is Run—48

Demo2 is Run—49

Demo2 is Run—50

Demo2 is Run—51

Demo2 is Run—52

Demo2 is Run—53

Demo2 is Run—54

Demo2 is Run—55

Demo2 is Run—56

Demo2 is Run—57

Demo2 is Run—58

Demo2 is Run—59

Main is Run—0

Main is Run—1

Main is Run—2

Main is Run—3

Main is Run—4

Main is Run—5

Main is Run—6

Main is Run—7

Main is Run—8

Main is Run—9

Main is Run—10

Main is Run—11

Main is Run—12

Main is Run—13

Main is Run—14

Main is Run—15

Main is Run—16

Main is Run—17

Main is Run—18

Main is Run—19

Main is Run—20

Main is Run—21

Main is Run—22

Main is Run—23

Main is Run—24

Main is Run—25

Main is Run—26

Main is Run—27

Main is Run—28

Main is Run—29

Main is Run—30

Main is Run—31

Main is Run—32

Main is Run—33

Main is Run—34

Main is Run—35

Main is Run—36

Main is Run—37

Main is Run—38

Main is Run—39

Main is Run—40

Main is Run—41

Main is Run—42

Main is Run—43

Main is Run—44

Main is Run—45

Main is Run—46

Main is Run—47

Main is Run—48

Main is Run—49

這就是run和start的差別。

5 小結

d.start();//開啟線程并執行該線程的run方法。

調用start()方法其實是調用系統的底層方法,啟動了一個新的線程,

這時候程式裡面除了main方法的主線程,還增加了一個新的線程。

d.run(); //僅僅是對象調用方法。而線程建立了,并沒有運作。

run方法僅僅是封裝了一部分代碼。

當主線程運作到run方法的時候,會停下來去調用run的方法,

直到循環結束,run方法運作完畢,

主線程才會繼續往下執行。

是以列印出來的結果一定是:

Demo2—59

Main—1

Main—49

四、總結

發現運作結果每一次都不同。

因為多個線程都擷取cpu的執行權。cpu執行到誰,誰就運作。

明确一點,在某一個時刻,隻能有一個程式在運作。(多核除外)

cpu在做着快速的切換,以達到看上去是同時運作的效果。

我們可以形象把多線程的運作行為在互相搶奪cpu的執行權。

這就是多線程的一個特性:随機性。誰搶到誰執行,至于執行多長,cpu說的算。

為什麼要覆寫run方法呢?

Thread類用于描述線程。

該類就定義了一個功能,用于存儲線程要運作的代碼。該存儲功能就是run方法。

也就是說Thread類中的run方法,用于存儲線程要運作的代碼。

多線程能提高效率

繼續閱讀