【Java|多线程与高并发】详解start()方法和run()方法的区别

news2024/11/16 19:33:37

文章目录

  • 前言
  • 1.start()方法和run()方法
  • 2.不能两次调用start()方法
  • 3.线程的执行是随机的
    • start()方法和run()方法的执行顺序不一定相同
  • 4.run()方法由JVM调用
    • public Thread(Runnable target)中的target

前言

本篇文章主要讲解以下几个问题:

  • start()方法和run()方法的区别与联系
  • 为什么不能连续两次调用shart()方法
  • run()方法中可能忽略的问题

1.start()方法和run()方法

我们在创建线程时,会重写run()方法.run()方法可以理解为线程要做的任务,但是直接调用run()方法,只是main线程也就是主线程去执行的,是没有新线程产生的
如果要想让线程去执行run()方法里面的代码,就需要让创建线程的对象去调用start()方法,shart()方法可以创建并启动线程,JVM调用run()方法后(后面会有介绍) 线程才会去执行

2.不能两次调用start()方法

同一个线程对象,只能调用一次start()方法,不能两次调用start()方法,调用两次的话,会抛出 IllegalThreadStateException 这个异常
示例如下:

public class Example6 {

    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            System.out.println("1");
        });
        t1.start();
        t1.start();
    }
}

在这里插入图片描述
为什么会这样?我们可以查看start()的源码
在这里插入图片描述
上面有一段话: A zero status value corresponds to state "NEW" 意思是 零状态值对应于状态“NEW”
线程运行时有六种状态,先熟悉一下,之后还会写文章进行详细介绍:

状态描述
新建(NEW)表示线程已经创建好了,但是还没有调用start()方法
就绪(RUNNABLE)表示线程可能在运行,也可能在就绪队列
阻塞 (BLOCKED)表示线程处于等在锁的状态
等待(WAITING)表示线程处于条件等待状态,当触发条件后会唤醒
计时等待(TIME_WAIT)比WAITING多了个超时条件触发的机制
终止(TERMINATED)表示线程执行结束

因此线程再调用start()方法之后,可能处于终止,或者其它非NEW状态,第二次调用的时候,相当于重新让线程运行一遍,从线程安全和线程本身的执行逻辑来看,都是不合理的,因此在调用start()方法之后,会对线程的状态进行一个判断,如果线程不是在NEW状态下,就会抛出异常

3.线程的执行是随机的

线程的执行是随机的,这也是个老生常谈的问腿了,究其原因还是因为线程的"抢占式执行",谁先"抢"到
操作系统分配的CPU资源,谁先去执行

start()方法和run()方法的执行顺序不一定相同

示例1:
看一下代码及代码运行结果

class MyThread extends Thread{
    private int val;
    public MyThread(int val) {
        this.val = val;
    }
    @Override
    public void run() {
        System.out.println(val);
    }
}
public class Example1 {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread(1);
        MyThread myThread2 = new MyThread(2);
        MyThread myThread3 = new MyThread(3);
        MyThread myThread4 = new MyThread(4);
        MyThread myThread5 = new MyThread(5);
        myThread1.start();
        myThread2.start();
        myThread3.start();
        myThread4.start();
        myThread5.start();

    }
}

在这里插入图片描述

由此我们可以看到虽然是myThread1先调用的start()方法,但是输出的结果却是在第二位,而myThread3后执行却在第一位
在这里插入图片描述
再次运行一次代码的执行结果虽然与上次不同,但仍然是随机的,当然也不是没有运行结果是1 2 3 4 5的可能

示例2:
看一下代码及代码运行结果

public class Example4 {
    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            while (true){
                System.out.println("t1");
            }
        });

        Thread t2 = new Thread(()->{
            while (true){
                System.out.println("t2");
            }
        });

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

    }
}

在这里插入图片描述

这里我们也能看到,start()执行的顺序与run()方法执行的顺序无关,随机执行t1和t2的run()方法 虽然这里是while(true),但是线程之间是相互独立的,所以并不影响
因此可以得出结论:start()方法和run()方法的执行顺序不一定相同

4.run()方法由JVM调用

start()执行完后,创建的新线程不会立刻去执行run()方法, run()方法会先被JVM去调用,之后对应的线程才会去执行.

public Thread(Runnable target)中的target

之前再讲创建线程的5种方法,介绍了实现Runnable接口,创建线程的方法
在这里插入图片描述

但其实这里面有一个坑,那就是public Thread(Runnable target)中的target参数,来看一下run()方法的底层源码

在这里插入图片描述
如果这里面的target不为空,才会去执行target的run()方法.如果传一个null,就不会去执行,如图所示:
在这里插入图片描述
代码如下:

class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("1");
    }
}
public class Example7 {
    public static void main(String[] args) {
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = null;
        Thread t1 = new Thread(myRunnable1);
        t1.start();
        Thread t2 = new Thread(myRunnable2);
        t2.start();
    }
}

因此要注意使用继承Runnable接口 创建线程的时候 要注意target不要为null

文章到这里去结束了,感谢观看!
“希望你继续兴致盎然的与世界交手,一直走在充满鲜花的道路”
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python cartopy绘制扇形区域图/cartopy绘制北极部分区域

问题 当绘图时,往往并不需要绘制整块区域,而是想聚焦于局部地区,此时我们需要绘制扇形图。 在cartopy中,只提供普通正方形的框架,如果我们需要其他,边界,需要自己去绘制,最常见的是…

程序分析与神经网络后门

原文来自微信公众号“编程语言Lab”:程序分析与神经网络后门 搜索关注“编程语言Lab”公众号(HW-PLLab)获取更多技术内容! 欢迎加入编程语言社区 SIG-程序分析,了解更多程序分析相关的技术内容。 加入方式:…

Nginx常用命令及具体应用(Linux系统)

目录 一、常用命令 1、查看Nginx版本命令,在sbin目录下 2、检查配置文件的正确性 3、启动和停止Nginx 4、查看日志,在logs目录下输入指令: 5、重新加载配置文件 二、Nginx配置文件结构 三、Nginx具体应用 1、部署静态资源 2、反向代…

MacOS Pytorch 机器学习环境搭建

学习 Pytorch ,首先要搭建好环境,这里将采用 Anoconda Pytorch PyCharm 来一起构建 Pytorch 学习环境。 1. Anoconda 安装与环境创建 Anoconda 官方介绍:提供了在一台机器上执行 Python/R 数据科学和机器学习的最简单方法。 为什么最简单…

springmvc考研交流平台 java ssm mysql

随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,考研交流平台当然也不能排除在外,从备考资料、课程学习的统计和分析,在过程中会产生大量的、各种各样的…

头戴式耳机适不适合跑步、最好用的跑步耳机推荐

现在爱好运动、重视健康的人越来越多,并且这部分群体呈现几何级增长,而这其中又有很多人喜欢边跑步时边听音乐,所以现如今跑步时听音乐是基本上已经成为很多运动人士的刚性需求。但实际上真正适合运动跑步的耳机并不多,我跑步差不…

程序员的自我修养第七章——动态链接 (下)

接上一篇。 7.3 地址无关代码 对于现代机器来说,引入地址无关代码并不麻烦,我们展示下各种模型的地址引用方式: 1. 模块内部函数调用 2. 模块内部的数据访问,如全局变量、静态变量。 3. 模块外部的函数调用,跳转。 4.…

【算法基础】字典树(Trie树)

一、Trie树原理介绍 1. 基本概念 Trie 树,也叫“字典树”。顾名思义,它是一个树形结构。它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题。【高效存储和查找字符串集合的数据结构】,存储形式如下: 2. 用数组来模拟Trie树的…

SpringBoot 启动配置文件加载和参数配置修改问题

SpringBoot 配置文件修正和参数覆盖SpringBoot 配置文件加载和参数覆盖1、SpringBoot 配置文件加载1.1、修改application.properties的参数几种方式1.2、方法一:直接CMD1.3、方法二:系统变量配置1.4、方法三:程序运行配置1.5、方法四&#xf…

【从零开始学C语言】知识总结一:C语言的基本知识汇总

C语言期末知识点总结 C语言期末试题(附答案)选择题编程题 2022C语言知识点大全【详细、必备】 C语言期末大作业-学生成绩管理系统(完整源码设计报告) C语言期末作业(15个)-货物管理系统、歌曲信息管理系…

Linux软件管理RPM

目录 前言 RPM软件管理程序:rpm RPM默认安装的路径 PRM讲解前准备工作 RPM安装(install) RPM查询(query) RPM卸载(erase) RPM升级与更新(upgrade/freshen) RPM重…

高压放大器在介电泳效应的细胞分选研究中的应用

实验名称:高压放大器在介电泳效应的细胞分选研究中的应用研究方向:生物医学测试目的:细胞分选在分析化学和生物医药领域有着非常重要的应用。在众多的分选方法中,微流控分选方法以其响应速度快、样品需求少等优点成为研究热门。微…

订单超时处理方案介绍

在电商场景下,一个订单流程中有许多环节要用到超时处理,包括但不限于: 买家超时未付款:比如超过15分钟没有支付,订单自动取消。 商家超时未发货:比如商家超过1个月没发货,订单自动取消。 买家…

【数据结构与算法】数组2:双指针法 二分法(螺旋矩阵)

文章目录今日任务1.Leetcode977:有序数列的平方(1)题目(2)思路(3)暴力排序(4)双指针法2.Leetcode209:长度最小的子数组(1)题目&#x…

数据库版本管理工具Flyway应用研究

目录1 为什么使用数据库版本控制2 数据库版本管理工具选型:Flyway、Liquibase、Bytebase、阿里 DMSFlywayLiquibaseBytebase阿里 DMS3 Flyway数据库版本管理研究3.1 参考资料3.2 Flyway概述3.3 Flyway原理3.4 Flyway版本和功能3.5 Flyway概念3.5.1 版本迁移&#xf…

聚观早报|马斯克有意出价45亿英镑收购曼联;威马员工将停薪留职

今日要闻:马斯克有意出价45亿英镑收购曼联;小米汽车接近获得新能源汽车生产资质;威马员工将停薪留职?;集度融合文心一言ChatGPT上车;三星 Galaxy S23 系列国行版发布马斯克有意出价45亿英镑收购曼联 据外媒…

帝国cms综合标签和数据库说明

帝国cms灵动标签e:loop的使用方法总结,是青青模板网整理的这些年使用帝国cms中经常使用的调用方法。帝国cms灵动标签顾名思义,灵活好用,通过简单的标签调用,就可以调用文字样式、图片样式,甚至是复杂的方案。下面是青青…

深入浅出带你学习WebSphere中间件漏洞

前言 上一篇文章给大家介绍了中间件glassfish的一些常见漏洞以及利用方法,今天我给大家带来的是WebSphere中间件的常见漏洞以及这些漏洞的利用方法,下面我们首先介绍一下WebSphere中间件是什么,然后展开来讲关于该中间件的漏洞。 WebSphere…

二面阿里巴巴成功上岸,准备了小半年,要个30k应该也算不上很高吧~

先说下我基本情况,本科不是计算机专业,现在是学通信,然后做图像处理,可能面试官看我不是科班出身没有问太多计算机相关的问题,因为第一次找工作,阿里的游戏专场又是最早开始的,就投递了&#xf…

【虚拟仿真】Unity3D打包WEBGL实现全屏切换

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 今天实现Unity3D打包WEBGL后实现按钮点击全屏和退出 全屏的实现…