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

多线程能提高效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员多线程练习题主要包括两个问题。第一个问题是如何控制四个线程在打印log之前能够同时开始等待1秒钟。一种解决思路是在线程的run方法中调用parseLog方法,并使用Thread.sleep方法让线程等待1秒钟。另一种解决思路是使用线程池,将线程数量固定为4个,并将每个调用parseLog方法的语句封装为一个Runnable对象,然后提交到线程池中。这样可以实现一秒钟打印4行日志,4秒钟打印16条日志的需求。 第二个问题是如何修改代码,使得几个线程调用TestDo.doSome(key, value)方法时,如果传递进去的key相等(equals比较为true),则这几个线程应互斥排队输出结果。一种解决方法是使用synchronized关键字来实现线程的互斥排队输出。通过给TestDo.doSome方法添加synchronized关键字,可以确保同一时间只有一个线程能够执行该方法,从而实现线程的互斥输出。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [黑马程序员——多线程10:多线程相关练习](https://blog.csdn.net/axr1985lazy/article/details/48186039)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值