IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 如何创建线程以及多线程的特征/优势 -> 正文阅读

[Java知识库]如何创建线程以及多线程的特征/优势


一、概念

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();
    }
}

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

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

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

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 11:39:48  更:2022-04-28 11:42:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:00:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码