如何创建线程以及多线程的特征/优势


一、概念

Java中的线程,是以轻量级进程来实现的

其他语言,可以是其他方式来实现,比如go,是协程的方式来实现(用户自己编写程序来实现线程,及线程的调度)

1.进程和线程的关联关系/区别

  1. 进程包含线程,一个进程至少包含一个线程
  2. 进程是系统分配资源的最小单位(基本单位),线程是操作系统调度cpu执行的最小单位(基本单位)
  3. 进程状态的改变会耗费很多时间,线程的效率更高
  4. 进程占用独立的虚拟地址空间,同一个进程中的多个线程可以共享这个进程的内存。

(1)一个进程要访问另一个的数据,需要使用通信的方式(代价比较大);同一个进程的线程,可以直接使用共享变量
(2)一个进程挂掉不会影响其他进程,但一个进程中的线程挂掉,就可能影响整个进程挂掉(比如一个线程申请的内存太多,超出整个进程的内存,就会挂掉(OOM))

线程和进程的状态:
在这里插入图片描述
线程和进程一样,系统也会创建pcb来管理

就绪:线程pcb不在队列的首部
运行:线程pcb处于cpu执行的时间片
状态改变比较耗时:
(1)创建
(2)销毁
(3)进入阻塞

线程和进程这些状态改变,都是比较耗时的,只是线程相对进程来说,耗时少一点

Java中,线程以轻量级进程的方式实现,也就具有进程的特征
需要系统调度cpu来执行:

  1. 并发:一个cpu以时间片轮转调度的方式,依次执行多个线程(人肉眼感知还是“同时”执行)
  2. 并行:多个cpu在一个时间点,同时执行多个线程

线程到底是就绪态,还是运行态,是操作系统调度决定,程序不知道
Java中,经常说并发编程,其实既包含多线程的并发,也有多线程的并行

二、创建线程

Java中,创建一个线程:
首先,Java程序要运行,必须先有一个main方法的入口类,先执行main方法(这里也会创建一个main线程)

是Java虚拟机创建的线程,然后执行main方法

1.继承Thread类

new Thread:创建一个Java中的线程对象(此时还没有创建系统中的线程(pcb))
在这里插入图片描述

2.实现Runnable接口

在这里插入图片描述

3.其他变形

3.本质还是继承Thread(匿名内部类)
在这里插入图片描述
4.实现Runnable接口(匿名内部类)
在这里插入图片描述
5.继承Thread(lambda表达式)
在这里插入图片描述
6.实现Runnable(lambda表达式)
在这里插入图片描述

4.总结

在我们理解上:
new Thread才能创建一个Java中的线程对象,调用start才会创建系统的线程,并申请系统调度执行
Runnable只是一个描述任务的对象,不是线程!

创建线程的方式:

  1. 继承Thread,重写run方法
  2. 实现Runnable接口,重写run方法
  3. 实现Callable接口(之后会补充)

三、多线程的作用/优势:增加运行速度

  1. 多个线程可以并发并行的执行,提高执行效率

main线程,总共循环20亿次++:

public class 多线程的优势_不使用多线程 {
    public static void main(String[] args) {
        //执行两次,每次循环++10亿次
        int num = 10_0000_0000;
        //记录执行的时间
        //返回这行代码执行时,从1970-01-01经过的毫秒数
        long start = System.currentTimeMillis();
        for(int i=0;i<2;i++){
            for(int j=0;j<num;j++){
                //这里不需要任何代码,j已经++10亿次了

            }
        }
        long end = System.currentTimeMillis();
        System.out.printf("执行时间:%s\n",end-start);
    }
}

两个线程同时并发并行的执行10亿次++:

public class 多线程的优势_使用多线程 {
    public static void main(String[] args) {
        //分别使用两个线程,每个执行10亿次++
        //开始的执行时间
        long start = System.currentTimeMillis();
        for(int i=0;i<2;i++){
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int j=0;j<10_0000_0000;j++){

                    }
                }
            });
        }
        //这里不能直接记录结束时间(注意:要使用debug运行,不能使用run)
        //以下代码的意思,是等两个thread线程执行完,main线程在往下执行
        //线程有main,两个new Thread创建的线程
        while(Thread.activeCount()>1){//activeCount返回活跃线程数
            Thread.yield();//main就让步(从运行态转为就绪态)
        }
        long end = System.currentTimeMillis();
        System.out.printf("执行时间:%s\n",end-start);
    }
}

每次++次数很大的时候,使用多线程效率高
++次数少的时候,不使用多线程效率高

多个线程执行任务,任务执行时间越长,相对线程的创建,占用的时间比例就越小,效率就更高
(任务执行时间很快,比如执行一次++,创建的时间就相对更多)
有多个耗时的任务,使用多线程效率更高

四、观察多线程并发并行的特征

两个线程,每个循环10次打印线程名和循环次数

从表现看:
单个线程执行顺序还是代码书写的顺序
多个线程代码之间,执行的顺序,就是并发并行的执行(随机)

public class 多线程并发特性_1 {
    public static void main(String[] args) {
        //设计两个线程,每个循环10次,每次打印一个语句
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                //Thread.currentThread返回这行代码运行时所在的线程引用
                //thread.getName返回线程的名称
                String name = Thread.currentThread().getName();
                for(int i=0;i<10;i++){
                    try {
                        Thread.sleep(10);
                        System.out.printf("线程:%s,执行第 %s 次\n",name,i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"t1");//创建线程时设置第二个参数,表示设置的线程名称

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                //Thread.currentThread返回这行代码运行时所在的线程引用
                //thread.getName返回线程的名称
                String name = Thread.currentThread().getName();
                for(int i=0;i<10;i++){
                    try {
                        Thread.sleep(100);
                        System.out.printf("线程:%s,执行第 %s 次\n",name,i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"t2");//创建线程时设置第二个参数,表示设置的线程名称

        t1.start();
        t2.start();
    }
}

执行结果:
在这里插入图片描述

五、多线程并发中创建耗时

在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dhdhdhdhg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值