JavaEE 【知识改变命运】02 多线程(1)

文章目录

  • 线程是什么?
    • 1.1概念
      • 1.1.1 线程是什么?
      • 1.1.2 为什么要有线程
      • 1.1.3 进程和线程的区别
      • 1.1.4 思考:执行一个任务,是不是创建的线程或者越多是不是越好?(比如吃包子比赛)
      • 1.1.5 ) Java 的线程 和 操作系统线程 的关系
    • 1.2 对多线程程序的理解
      • 1.2.1 ) Java 的线程 和 操作系统线程 的关系
    • 1.3 创建线程的两种方式
      • 1.3.1 继承 Thread 类
      • 1.3.2实现Runnable接口
      • 1.3.3两者创建方法的对比
      • 1.3.4 其他形式创建
        • 1.3.4.1 匿名类创建Thread子类对象
        • 1.3.4.2匿名内部类创建 Runnable ⼦类对象
        • 1.3.4.2 lambda 表达式创建 Runnable ⼦类对象
    • 1.4 jconsloe使用

线程是什么?

1.1概念

1.1.1 线程是什么?

  1. 线程是就是一个执行流,每个执行流之间都可以按照一定顺子执行自己的代码,多个线程可以”同时“执行多分代码
  2. 举例:进程就像一个程序,比如qq,迅雷,进程是程序的一次执行过程,或者是正在运行的一个程序,是动态的过程有它自己的产生存在和消亡的过程
  3. 线程是又进程创建的,是进程的一个实体,一个进程可以拥有多个线程,把迅雷比作一个进程,而同时下载多条视频,就是多条线程在工作。

1.1.2 为什么要有线程

  1. “并发式编成”已经成为了编成界的“刚需”
  2. 单核 CPU 的发展遇到了瓶颈. 要想提⾼算⼒, 就需要多核 CPU. ⽽并发编程能更充分利⽤多核 CPU资源.
  3. 有些任务场景需要 “等待 IO”, 为了让等待 IO 的时间能够去做⼀些其他的⼯作, 也需要⽤到并发编程.
  4. 重点:进程虽然可以进程并发编成,但是线程比进程更轻量。

解释:进程的创建也需要申请资源,而申请资源对于系统的性能影响比较大。
在这里插入图片描述
举个例子:张三要开一个工厂,工业园相当于是操作系统,地皮是固定的,张三的工厂就像一个进程,生产线就像一个线程,张三的工厂是生产皮包的,里面只有一条生产线,现在我们要提高产量,是重新建一个场比较好?,还是在原来的工厂中加一条生产线好呢?,肯定是只增加一条生产线,这样就节省了工业园地皮的面积资源,也利用张三工厂的面积资源,线程的出现更好的利用了系统的资源。
在这里插入图片描述

  1. 其次, 虽然多进程也能实现 并发编程, 但是线程⽐进程更轻量,

创建线程比创建进程更快
销毁线程比销毁进程更快
调度线程比调度进程更快。

  1. 线程虽然比进程更轻量,但是⼈们还不满⾜, 于是⼜有了 “线程池”(ThreadPool) 和 “协程”(Coroutine)

1.1.3 进程和线程的区别

1.进程里面包含线程:每一个进程里面至少包含一个主线程
2.进程是申请资源的最小单位
3.线程是cpu调度的最小单位
4.进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间 ,所以进程与进程之间互不影响,线程与线程之间可能产生影响
5.一个线程受到影响,会导致进程的结束,⼀个进程挂了⼀般不会影响到其他进程. 但6.是⼀个线程挂了, 可能把同进程内的其他线程⼀起带⾛(整个进程崩溃).
在这里插入图片描述

1.1.4 思考:执行一个任务,是不是创建的线程或者越多是不是越好?(比如吃包子比赛)

我们先思考下创造进程的方式:
在这里插入图片描述
虽然双进程比单进程确实提升了效率,但是消耗资源太大了,太浪费资源了
我们思考创建线程的方法
在这里插入图片描述
效率确实提高了,比进程消耗的资源小

我们再思考一下,根据上面的情况,我们无限创建线程,是不是线程创建的越多越好呢?
在这里插入图片描述
答案肯定不是的,这样会出现线程争抢资源问题,如果一个线程崩溃就会造成整个进程的崩溃

其实我们可以根据cpu的逻辑处理器来创建线程
在这里插入图片描述

当线程小于逻辑处理器,创建线程会提升效率
当线程大于逻辑处理器,创建线程的线程都是阻塞等待状态,从而没有发挥出线程的效果,创建线程本来就会消耗资源,从而白白消耗资源

  • 总结:通过提升线程,我们可以提高效率,但是要根据实际情况来创建,不能盲目创建

1.1.5 ) Java 的线程 和 操作系统线程 的关系

线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对⽤⼾层提供了⼀些 API 供⽤⼾使⽤(例如 Linux 的 pthread 库).Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装.

1.2 对多线程程序的理解

1.2.1 ) Java 的线程 和 操作系统线程 的关系

  1. 线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对⽤⼾层提供了⼀些 API 供⽤⼾使⽤(例如 Linux 的 pthread 库).Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装.
  2. 线程与普通程序的区别:每个线程都是⼀个独⽴的执⾏流,多个线程之间是 “并发” 执⾏的

import java.util.Random; public class ThreadDemo {
    private static class MyThread extends Thread {
        @Override
        public void run() {
            Random random = new Random();
            while (true) {
                // 打印线程名称
                System.out.println(Thread.currentThread().getName());
                try {
                    // 随机停⽌运⾏ 0-9 秒
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();
        Random random = new Random();
        while (true) {
            // 打印线程名称
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(random.nextInt(10));
            } catch (InterruptedException e) {
                // 随机停⽌运⾏ 0-9 秒
                e.printStackTrace();
            }
        }
    } }

在这里插入图片描述

我们可以jconsole这个工具查看线程
在这里插入图片描述
里面有一个mian主线程,和Thread-0子线程

1.3 创建线程的两种方式

1.3.1 继承 Thread 类

    @Override
    //自定义的线程的执行体,线程执行的代码写在这里
    public void run(){
        while (true){
            System.out.println("hello myThread ");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    } } class Main{
    public static void main(String[] args) {
        MyThread myThread=new MyThread();//创建一个线程对象
        myThread.start();//启动线程

        while (true){
            System.out.println("hello mainThread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

在这里插入图片描述
1:PCB是操作系统层面的
2:Thread是java层面的线程。两者是一 一对应的
3:过程:java创建一个线程------jvm调用系统API--------创建系统中线程------参与调度cpu
在这里插入图片描述
4. 线程执行的顺序是没有规律的,跟cpu的调度有关,因为cpu是“抢占式”执行,所以那个线程当前占用cpu资源是不能确定的
5.能不能调用run()方法执行线程,答案是不行的,因为run方法是java层面的,是不能启动线程的。
6:
在这里插入图片描述

start()开始后,并不意味着线程立马执行,在这里插入图片描述

1.3.2实现Runnable接口

    @Override
    public void run() {
        while (true){
            System.out.println("hello myRunnable");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

} class Main{
    public static void main(String[] args) {
        MyRunnable myRunnable=new MyRunnable();//创建一个线程任务对象
       // 创建 Thread 类实例, 调⽤ Thread 的构造⽅法时将 Runnable 对象作为 target 参数.
        Thread thread=new Thread(myRunnable);//创建一个线程对象,
        thread.start();//启动线程
        while (true){
            System.out.println("hello mainThread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    } } ```

这种方法实现底层原码过程:
在这里插入图片描述

其实这种模式是一种及简化的代理模式,这里模拟实现一下

//模拟实现一个Thread类的代理类,模拟Thread的启动
public class ThreadProxy implements Runnable{
    private Runnable target;
    public ThreadProxy(Runnable target) {
        this.target = target;
    }
    @Override
    public void run(){
        if (target!=null){
            target.run();
        }
    }
    public void start(){
        start0();
    }

    private void start0() {
        run();
    }

}
class Main{
    public static void main(String[] args) {
//        ThreadProxy threadProxy01 = new ThreadProxy(new Runnable() {
//            @Override
//            public void run() {
//                while (true){
//                    System.out.println("hello myRunnable");
//                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        });
//        threadProxy01.start();
        Tiger tiger = new Tiger();
        ThreadProxy threadProxy02 = new ThreadProxy(tiger);

        threadProxy02.start();
    }
}
class animal {
}
class Tiger extends animal implements Runnable{


    public void run(){
        System.out.println("老虎嗷嗷叫");
    }
}

1.3.3两者创建方法的对比

  1. 继承 Thread 类, 直接使⽤ this 就表⽰当前线程对象的引⽤.
  2. 实现 Runnable 接⼝, this 表⽰的是 MyRunnable 的引⽤. 需要使⽤Thread.currentThread()
  3. java是单继承模式,在某种情况下一个类可能已经继承某个父类,这时在用来继承Thread类的方法创造线程是显然不可能的
  4. 实现 Runnable 接⼝,实现了高内聚低耦合的特点,线程和业务逻辑分开,后面修改代码时候,相互影响最小化。
    解释:举例一个场景:两条生成皮鞋的生产线,一条生产皮包生产线
    在这里插入图片描述

1.3.4 其他形式创建

1.3.4.1 匿名类创建Thread子类对象
public class Main {
    public static void main(String[] args) {
        Thread t1=new Thread(){
            @Override
            public void run() {
                while (true){
                    System.out.println("hello myThread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t1.start();
    }
    
}
1.3.4.2匿名内部类创建 Runnable ⼦类对象
public class Main {
    public static void main(String[] args) {
        Thread t2=new Thread(new Runnable(){
            @Override
            public void run() {
                while (true){
                    System.out.println("hello myRunnable");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t2.start();
    }
}

1.3.4.2 lambda 表达式创建 Runnable ⼦类对象
public class Main {
    public static void main(String[] args) {
        Thread t3=new Thread(()->{
            while (true){
                System.out.println("hello myLambda");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t3.start();
   }

}

1.4 jconsloe使用

在这里插入图片描述
我们这里重提一下,先调用的方法会先入栈,后调用的后入栈,后调用的方法执行完后就会出栈。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921969.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 力扣 热题 100道(八)相交链表(C++)

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后&…

全面解析 JMeter 后置处理器:概念、工作原理与应用场景

在性能测试中,Apache JMeter是一个非常流行的工具,它不仅能够模拟大量用户进行并发访问,还提供了丰富的扩展机制来满足各种复杂的测试需求。后置处理器(Post-Processor)是JMeter中非常重要的组件之一,用于在…

java八股-SpringCloud微服务-Eureka理论

文章目录 SpringCloud架构Eureka流程Nacos和Eureka的区别是?CAP定理Ribbon负载均衡策略自定义负载均衡策略如何实现?本章小结 SpringCloud架构 Eureka流程 服务提供者向Eureka注册服务信息服务消费者向注册中心拉取服务信息服务消费者使用负载均衡算法挑…

每天五分钟机器学习:支持向量机数学基础之超平面分离定理

本文重点 超平面分离定理(Separating Hyperplane Theorem)是数学和机器学习领域中的一个重要概念,特别是在凸集理论和最优化理论中有着广泛的应用。该定理表明,在特定的条件下,两个不相交的凸集总可以用一个超平面进行分离。 定义与表述 超平面分离定理(Separating Hy…

day05(单片机高级)PCB基础

目录 PCB基础 什么是PCB?PCB的作用? PCB的制作过程 PCB板的层数 PCB设计软件 安装立创EDA PCB基础 什么是PCB?PCB的作用? PCB(Printed Circuit Board),中文名称为印制电路板,又称印刷…

电脑自动关机时间如何定?Wise Auto Shutdown 设置关机教程

在日常使用电脑的过程中,有时我们需要让电脑在特定的时间自动关机,比如在下载大文件完成后、执行长时间的任务结束时,或者只是单纯想在某个预定时间让电脑自动关闭以节省能源。这时候,Wise Auto Shutdown 这款软件就能派上大用场了…

Lucene(2):Springboot整合全文检索引擎TermInSetQuery应用实例附源码

前言 本章代码已分享至Gitee: https://gitee.com/lengcz/springbootlucene01 接上文。Lucene(1):Springboot整合全文检索引擎Lucene常规入门附源码 如何在指定范围内查询。从lucene 7 开始,filter 被弃用,导致无法进行调节过滤。 TermInSetQuery 指定…

使用Kubernetes部署第一个应用

目录 前提条件 启动集群 部署 nginx 应用 创建 YAML 文件 应用 YAML 文件 查看部署结果 理解Pods 相关命令 公布应用程序 问题背景 Kubernetes Service(服务)概述 服务和标签 为Deployment 创建一个 Service 伸缩应用程序 Scaling&#x…

使用 Maven 创建 jar / war 项目

使用 Maven 创建 jar 项目 maven-archetype-quickstart 这个Archetype,基本内容包括: 一个包含junit依赖声明的 pom.xml 、src/main/java主代码目录及一个名为App的类 、src/test/java测试代码目录及一个名为 AppTest的测试用例maven-archetype-webapp 一…

HDR视频技术之四:HDR 主要标准

HDR 是 UHD 技术中最重要维度之一,带来新的视觉呈现体验。 HDR 技术涉及到采集、加工、传输、呈现等视频流程上的多个环节,需要定义出互联互通的产业标准,以支持规模化应用和部署。本文整理当前 HDR 应用中的一些代表性的国际标准。 1 HDR 发…

Ubuntu中使用多版本的GCC

我的系统中已经安装了GCC11.4,在安装cuda时出现以下错误提示: 意思是当前的GCC版本过高,要在保留GCC11.4的同时安装GCC9并可以切换,可以通过以下步骤实现: 步骤 1: 安装 GCC 9 sudo apt-get update sudo apt-get ins…

dubbo-go框架介绍

框架介绍 什么是 dubbo-go Dubbo-go 是 Apache Dubbo 的 go 语言实现,它完全遵循 Apache Dubbo 设计原则与目标,是 go 语言领域的一款优秀微服务开发框架。dubbo-go 提供: API 与 RPC 协议:帮助解决组件之间的 RPC 通信问题&am…

DataGear 5.2.0 发布,数据可视化分析平台

DataGear 企业版 1.3.0 已发布,欢迎体验! http://datagear.tech/pro/ DataGear 5.2.0 发布,图表插件支持定义依赖库、严重 BUG 修复、功能改进、安全增强,具体更新内容如下: 重构:各模块管理功能访问路径…

2023年3月GESPC++一级真题解析

一、单选题(每题2分,共30分) 题目123456789101112131415答案BAACBDDAADBCDBC 1.以下不属于计算机输入设备的有( )。 A .键盘 B .音箱 C .鼠标 D .传感器 【答案】 …

RabbitMQ2:介绍、安装、快速入门、数据隔离

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

vue2.0 luoyi框架 代码漏洞检查问题

检查出在element ui存在漏洞 经过在elemen-ui.common.js文件中查找没发现eval函数 后发现是打包之后生成的产物 解决方法 在vue.config.js文件中进行打包配置 configureWebpack: {devtool: source-map, // 禁用 eval,使用 source-map 进行源码映射},

管家婆财贸ERP BR035.回款利润明细表

最低适用版本: 财贸系列 23.5 插件简要功能说明: 报表统计销售单/销售退货单/销售发票回款情况更多细节描述见下方详细文档插件操作视频: 进销存类定制插件--回款利润明细表 插件详细功能文档: 1. 应用中心增加报表【回款利润明细表】 a. b. 查询条件: ⅰ. 日期区间:…

学习QT第二天

QT6示例运行 运行一个Widgets程序运行一个QT Quick示例 工作太忙了,难得抽空学点东西。-_-||| 博客中有错误的地方,请各位道友及时指正,感谢! 运行一个Widgets程序 在QT Creator的欢迎界面中,点击左侧的示例&#xf…

【图像检测】深度学习与传统算法的区别(识别逻辑、学习能力、泛化能力)

识别逻辑 深度学习 使用了端到端的学习策略,直接学习从图像到检测结果的映射关系,自动提取特征,并且根据特征与特征之间的关系,计算出检测结果。 传统算法 则是人工提取特征,比如边缘特征,直线特征&#x…

2024数学建模亚太赛【C题】赛题详细解析

目录 📑一、竞赛时间 🗝️二、奖项设置 ✏️三、选题思路 🔍阶段一:【数据预处理与探索性分析】 1.【数据清洗与预处理】 2.【探索性数据分析(EDA)】 🔍阶段二:【时间序列建模…