天天看点

黑马程序员_日记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方法,用于存储线程要运行的代码。

多线程能提高效率

继续阅读