多线程原理和常用方法以及Thread和Runnable的区别

文章目录

    • 🍦多线程原理
      • 🍧随机性打印
      • 🍨多线程内存图解
    • 🍩Thread类的常用方法
      • 🍪获取线程名称 getName()
      • 🎂设置线程名称 setName() 或者 new Thread("线程名字")
      • 🍰使当前正在执行的线程以指定的毫秒数暂停 sleep(long millis)
    • 🥧创建多线程程序的第二种方式-实现Runnable接口
    • 🍫Thread和Runnable的区别
    • 🍬使用匿名内部类开启线程

🍦多线程原理

多线程是一种并发执行的编程技术,它允许程序同时执行多个线程(线程是进程内的独立执行单元)。多线程的主要目的是提高程序的执行效率和响应速度。下

🍧随机性打印

CPU有了两条执行的路径,CPU就有了选择 ,一会执行main方法 一会执行run方法。
也可以说两个线程,一个main线程 一个run线程 一起请求CPU的执行权(执行时间)谁抢到了就执行对应的代码
多线程随机性打印结果

🍨多线程内存图解

  1. main方法的第一步创建对象,创建对象开辟堆内存存储在堆内存中(地址值赋值给变量名0x11)
  2. mt.run()调用时 run方法被压栈进来 其实是一个单线程的程序(main线程,会先执行完run方法再执行主线程中的去其他方法)
  3. mt.start()调用时会开辟一个新的栈空间。执行run方法(run方法就不是在main线程执行,而是在新的栈空间执行,如果再start会再开辟一个栈空间再多一个线程)

对cpu而言,cpu就有了选择的权利 可以执行main方法、也可以执行两个run方法。
多线程好处:多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间,多个线程互不影响 进行方法的压栈和弹栈。
多线程内存图解

🍩Thread类的常用方法

🍪获取线程名称 getName()

public static void main(String[] args) {
    //创建Thread类的子类对象
    MyThread mt = new MyThread();
    //调用start方法,开启新线程,执行run方法
    mt.start();

    new MyThread().start();
    new MyThread().start();

    //链式编程
    System.out.println(Thread.currentThread().getName());
}

/**
    获取线程的名称:
        1.使用Thread类中的方法getName()
            String getName() 返回该线程的名称。
        2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称
            static Thread currentThread() 返回对当前正在执行的线程对象的引用。
 * @author zjq
 */
// 定义一个Thread类的子类
public class MyThread extends Thread{
    //重写Thread类中的run方法,设置线程任务
    @Override
    public void run() {
        //获取线程名称
        //String name = getName();
        //System.out.println(name);

        //链式编程
        System.out.println(Thread.currentThread().getName());
    }
}

输出如下:

main
Thread-2
Thread-0
Thread-1

🎂设置线程名称 setName() 或者 new Thread(“线程名字”)

  1. 使用Thread类中的方法setName(名字)
    void setName(String name) 改变线程名称,使之与参数 name 相同。

  2. 创建一个带参数的构造方法,参数传递线程的名称;调用父类的带参构造方法,把线程名称传递给父类,让父类(Thread)给子线程起一个名字

    Thread(String name) 分配新的 Thread 对象。
    代码案例:

//开启多线程
MyThread mt = new MyThread();
mt.setName("小强");
mt.start();

//开启多线程
new MyThread("旺财").start();

🍰使当前正在执行的线程以指定的毫秒数暂停 sleep(long millis)

代码案例:

public static void main(String[] args) {
        //模拟秒表
        for (int i = 1; i <=60 ; i++) {
            System.out.println(i);

            //使用Thread类的sleep方法让程序睡眠1秒钟
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

🥧创建多线程程序的第二种方式-实现Runnable接口

实现Runnable接口实现多线程的步骤:

  1. 创建一个Runnable接口的实现类
  2. 在实现类中重写Runnable接口的run方法,设置线程任务
  3. 创建一个Runnable接口的实现类对象
  4. 创建Thread类对象,构造方法中传递Runnable接口的实现类对象
  5. 调用Thread类中的start方法,开启新的线程执行run方法

代码案例如下:

/**
 * 1.创建一个Runnable接口的实现类
 * @author zjq
 */
public class RunnableImpl implements Runnable{
    //2.在实现类中重写Runnable接口的run方法,设置线程任务
    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}


public static void main(String[] args) {
    //3.创建一个Runnable接口的实现类对象
    RunnableImpl run = new RunnableImpl();
    //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
    Thread t = new Thread(run);//打印线程名称
    //5.调用Thread类中的start方法,开启新的线程执行run方法
    t.start();

    for (int i = 0; i <20 ; i++) {
        System.out.println(Thread.currentThread().getName()+"-->"+i);
    }
}

🍫Thread和Runnable的区别

实现Runnable接口创建多线程程序的好处:

  1. 避免了单继承的局限性

一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类。
实现了Runnable接口,还可以继承其他的类,实现其他的接口。

  1. 增强了程序的扩展性,降低了程序的耦合性(解耦)

实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)。
实现类中,重写了run方法:用来设置线程任务。
创建Thread类对象,调用start方法:用来开启新线程。

🍬使用匿名内部类开启线程

匿名内部类开启线程可以简化代码的编码。
代码案例如下:

/**
    匿名内部类方式实现线程的创建

    匿名:没有名字
    内部类:写在其他类内部的类

    匿名内部类作用:简化代码
        把子类继承父类,重写父类的方法,创建子类对象合一步完成
        把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成
    匿名内部类的最终产物:子类/实现类对象,而这个类没有名字

    格式:
        new 父类/接口(){
            重复父类/接口中的方法
        };
 * @author zjq

 */
public class Demo01InnerClassThread {
    public static void main(String[] args) {
        //线程的父类是Thread
        // new MyThread().start();
        new Thread(){
            //重写run方法,设置线程任务
            @Override
            public void run() {
                for (int i = 0; i <20 ; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"詹");
                }
            }
        }.start();

        //线程的接口Runnable
        //Runnable r = new RunnableImpl();//多态
        Runnable r = new Runnable(){
            //重写run方法,设置线程任务
            @Override
            public void run() {
                for (int i = 0; i <20 ; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"线程");
                }
            }
        };
        new Thread(r).start();

        //简化接口的方式
        new Thread(new Runnable(){
            //重写run方法,设置线程任务
            @Override
            public void run() {
                for (int i = 0; i <20 ; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"zjq");
                }
            }
        }).start();
    }
}

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。
主页:共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃

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

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

相关文章

数据挖掘实战:基于 Python 的个人信贷违约预测

本次分享我们 Python 觅圈的一个练手实战项目&#xff1a;个人信贷违约预测&#xff0c;此项目对于想要学习信贷风控模型的同学非常有帮助。 技术交流 技术要学会交流、分享&#xff0c;不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。 好的文章离不开粉丝的分享、…

ssm+java车辆售后维护系统 springboot汽车保养养护管理系统+jsp

以前汽车维修人员只是在汽车运输行业中从事后勤保障工作,随着我国经济的发展,汽车维修行业已经从原来的从属部门发展成了如今的功能齐备的独立企业。这种结构的转变,给私营汽修企业和个体汽修企业的发展带来了契机,私营企业和个体维修企业的加入也带动了整个汽修行业的整体水平…

Python中进行特征重要性分析的8个常用方法

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在机器学习和数据科学领域&#xff0c;理解特征在模型中的重要性对于构建准确且可靠的预测模型至关重要。Python提供了多种强大的工具和技术&#xff0c;能够探索特征重要性的各个方面。 本文将详细介绍8种常用…

Linux系统:使用CloudDrive实现云盘本地挂载

此处以不使用Docker服务 系统&#xff1a; Ubuntu22.04 硬件信息&#xff1a; x86_64 1 安装CloudDrive CloudDrive下载地址 在服务器上安装fusemount3 sudo apt-get -y install fuse3下载对应版本的CloudDrive压缩包&#xff0c;我的机器为&#xff1a;clouddrive-2-linux-…

外汇天眼:外汇市场是由哪些层级构成?

除了一般投资人外&#xff0c;外汇市场基本上可分为以下三个层级&#xff1a; 第一层级&#xff1a;顶级做市商 顶级做市商&#xff1a;各大大型银行、央行和一些非银行做市商 根据2016年的Euromoney调查外汇显示&#xff1a;外汇市场最顶端的无疑是各大银行做市商&#xff…

【IEEE出版|往届均已成功EI检索】2024年第四届消费电子与计算机工程国际学术会议(ICCECE 2024)

2024年第四届消费电子与计算机工程国际学术会议&#xff08;ICCECE 2024&#xff09; 2024 4th International Conference on Consumer Electronics and Computer Engineering 进入21世纪以来&#xff0c;计算机技术的高速发展带来了消费电子产品的快速更迭。在技术迅速发展历…

虚假IP地址攻击的溯源方法

随着网络技术的迅速发展&#xff0c;网络攻击行为也日益猖獗。其中&#xff0c;虚假IP地址攻击是一种较为常见的网络攻击方式&#xff0c;它利用虚假的IP地址&#xff0c;通过互联网对目标进行攻击和入侵。这种攻击方式不仅难以追踪&#xff0c;而且往往会给企业和个人带来巨大…

浮点运算误差

输出所有形如aabb的4位完全平方数&#xff08;即前两位数字相等&#xff0c;后两位数字也相等&#xff09; 解决这个问题首先需要表示aabb这个变量&#xff0c;只需要定义一个变量n存储即可&#xff0c;另一个问题就是如何判断n是否为完全平方数&#xff1f; 第一种思路是先求出…

大数据Doris(三十一):Doris简单查询

文章目录 Doris简单查询 一、简单查询 二、Join

Unity 使用Horizontal Layout Group和Toggle制作多个水平开关按钮实现自动排列和单个点击放大后的自动排列。

Unity的布局组件Horizontal Layout Group是很好用的&#xff0c;当然也包括其它布局组件也一样好用。 比如要实现多按钮开关自动水平排列&#xff0c;那么就可以使用它了。 首先我们为按钮创建个父物体&#xff08;我这里使用了Scroll View中的Content作为父物体&#xff09;…

深度解析 Dockerfile:构建可重复、可扩展的Docker镜像

文章目录 什么是Dockerfile&#xff1f;Dockerfile的基本结构常用Dockerfile指令解析1. FROM2. LABEL3. WORKDIR4. COPY5. RUN6. EXPOSE7. ENV8. CMD 构建可重复、可扩展的Docker镜像1. 指定基础镜像的版本2. 合理使用缓存3. 精简镜像4. 使用多阶段构建 总结 &#x1f388;个人…

运维知识点-Nginx

Nginx Nginx解析安全实战预备知识实验目的#制作图片木马# web服务器-Nginx服务命令及配置centOS7安装安装所需插件安装gccpcre、pcre-devel安装zlib安装安装openssl Nginx解析安全实战 预备知识 NginxPHP/FastCGI构建的WEB服务器工作原理 Nginx|FastCGI简介 Nginx (“engin…

7.ROS的TF坐标变换(一):TF简介及静态坐标变换代码讲解

目录 1 什么是ROS的TF坐标变换TransForm Frame 2 坐标变换的msg信息geometry_msgs/TransformStamped与geometry_msgs/PointStamped 3 静态坐标变换 3.1 C clion实现静态坐标变换 3.1.1 CMakeLists.txt配置 3.1.2 package.xml配置 3.1.3 发布节点建立 3.1.4 接收节点建立…

R语言实验三

1、读取一个文件并进行如下操作。 ①使用命令清空工作空间&#xff0c;使用read.table读取exam_1.txt文件&#xff0c;将文件保存到data变量中&#xff0c;数据第一行设置为列名&#xff0c;第一列是行名。 ②判断对象data是否为矩阵。 ③将对象转换为矩阵&#xff0c;记为d…

L1-006:连续因子

题目描述 一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3567&#xff0c;其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N&#xff0c;要求编写程序求出最长连续因子的个数&#xff0c;并输出最小的连续因子序列。 输入格式&#xff1a; 输入在一行…

nodejs_vue+vscode美容理发店会员管理系统un1dm

按照设计开发一个系统的常用流程来描述系统&#xff0c;可以把系统分成分析阶段&#xff0c;设计阶段&#xff0c;实现阶段&#xff0c;测试阶段。所以在编写系统的说明文档时&#xff0c;根据系统所处的阶段来描述系统的内容。 绪论&#xff1a;这是对选题的背景&#xff0c;意…

【涂鸦T2-U】2、添加光感bh1750

文章目录 前言一、基础介绍二、电路图2.1 电路图12.2 电路图2——实际采用 三、代码四、编译五、刷机六、测试结果小结 前言 本章介绍如何在涂鸦T2-U开发板上添加光感bh1750驱动并实现定时读取数据。 一、基础介绍 BH1750( GY-302 )光照传感器 这篇文章有bh1750的基础介绍。…

面试问的最多的时候

1&#xff1a;kafuka消息队列不丢数据 2&#xff1a;MVC的流转 3&#xff1a;线程池 4&#xff1a;liunx 5&#xff1a;k8s 6&#xff1a;负载过高 7&#xff1a;索引 8&#xff1a;事务 9&#xff1a;监听 10&#xff1a;动态路由 11&#xff1a;业务模块 12&#x…

最短路算法

文章目录 最短路总览朴素Dijkstra - 稠密图 - O ( n 2 ) O(n^2) O(n2)具体思路时间复杂度分析使用场景AcWing 849. Dijkstra求最短路 ICODE 堆优化 D i j k s t r a Dijkstra Dijkstra 算法 - 稀疏图 - O ( m l o g n ) O(mlogn) O(mlogn)具体思路和时间复杂度分析使用场景A…

【HuggingFace Transformer库学习笔记】基础组件学习:Tokenizer

基础组件——Tokenizer &#xff08;1&#xff09;模型加载 from transformers import AutoTokenizersen "弱小的我也有大梦想!" # 从HuggingFace加载&#xff0c;输入模型名称&#xff0c;即可加载对于的分词器 tokenizer AutoTokenizer.from_pretrained("m…