【JavaEE多线程】线程的创建

系列文章目录

🌈座右铭🌈:人的一生这么长、你凭什么用短短的几年去衡量自己的一生!

💕个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C++,自顶向下看Java-CSDN博客

❤️相关文章❤️:清灵白羽 漾情天殇-CSDN博客


目录

系列文章目录

前言

一、继承Thread类

        1、创建自定义线程类

        2、创建线程对象并且启动

        3、线程生命周期

        拓展:start()和run()的区别

        1、run()方法

        2、start()方法

二、实现Runnable接口

        1、实现Runnable接口

        1、创建线程任务类

        2、创建线程对象并且传入线程任务

        3、启动线程

        2、以上两种方式的区别

        1、Runnable当中的this引用

        2、Thread继承类当中的this引用

三、匿名内部类创建线程

        1、匿名内部类创建Thread对象

        2、匿名内部类创建Runnable子类对象


前言

        今天的这篇文章主要为大家介绍一下Java当中的线程是如何创建的,这里为大家分别介绍了几种方式,内容比较简单,但是涉及到了之前JavaSE的一些语法细节,如果有遗忘的话大家可以翻阅我之前的文章,能够帮助到各位就是对我最大的鼓励!


一、继承Thread类

        首先我提示一下这里使用到了多态的语法概念如果对于这方面内容有不了解的话可以先去复习一下多态的概念,或者看我之前介绍过有关多态的文章。

        1、创建自定义线程类

        首先我们需要创建一个自定义的线程类,该类继承自Thread类,并且重写了其中的run()方法,以定义线程的执行逻辑。

package Yangon;

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("线程执行!");
    }
}
public class Main {
}

        2、创建线程对象并且启动

        创建自定义的线程类的对象,并且调用其start()方法,以启动线程。

public class Main {
    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();
    }
}

        这里就使用到了向上转型,使用多态。

        3、线程生命周期

        当调用线程对象的start()方法时,线程进入就绪状态,等待CPU的调度执行,一旦CPU调度到该线程的时候就会执行其中的run()方法,当run()方法执行完毕或者线程被中断的时候线程就会结束等待下一次调用或者直接销毁。

        我在这里多说一句,线程的创建并不一定要使用多态,也可以直接使用Thread来创建新的线程,直接给Thread传递一个Runnable(这个东西我一会会讲)即可。

public class Main {
    public static void main(String[] args) {
        Runnable myRunnable = () -> {
            // 在这里定义线程的执行逻辑
            System.out.println("MyThread is running...");
        };
        
        Thread myThread = new Thread(myRunnable);
        myThread.start();
    }
}

        拓展:start()和run()的区别

        在Java当中,线程的启动涉及到两个重要的方法,run方法和start方法,他们之间却有着很大的区别:

        1、run()方法

        只是Thread的一个普通的方法用以定义线程的执行逻辑,当我们直接调用一个线程对象的run方法的时候并不会线程新的线程,而是在当前线程当中执行run方法的代码。如果我们通过继承Thread类并且重写其run方法来创建新的线程时,当我们调用该线程的run方法实际上只是在当前线程中执行了自己定义的新线程的run方法,并没有新的线程产生,程序还是只有一个执行流。

        2、start()方法

        start()方法是一个用于启动一个新线程的重要方法,当我们调用一个线程对象的start方法的时候,系统会为该线程创建一个新的线程,并且在新线程当中调用run方法,同样的使用继承Thread类来创建新线程的方法时,我们调用start方法,系统产生一个新线程并且在新线程当中执行run方法,这个时候系统有两个执行流。这就是他们之间的区别。


二、实现Runnable接口

        1、实现Runnable接口

        1、创建线程任务类

        首先,我们需要创建一个类,实现Runnable接口,并且重写其中的run()方法,定义线程当中的执行逻辑。

class MyTask implements Runnable{
    @Override
    public void run() {
        System.out.println("线程执行");
    }
}

        2、创建线程对象并且传入线程任务

        接下来我们需要创建一个Thread类的对象,并且将实现了Runnable接口的线程任务对象作为参数传递给Thread的构造方法。

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyTask());
        thread.start();
    }
}

        3、启动线程

        最后我们只需要调用start()方法启动线程即可。通过实现Runnable接口来创建新线程的优势在于能够更好地支持面向对象的设计原则,并且提供了更好的线程任务与线程类的解耦,此外通过实现Runnable接口,多个线程可以共享同一个线程任务对象,避免了多重继承带来的局限性,因此我们推荐使用Runnable接口的方法创建新线程。

        2、以上两种方式的区别

        继承Thread类,直接使用this引用表示当前线程对象的引用,如果是实现Runnable接口,this表示的是MyTask的引用,需要使用Thread.currentThread()解释一下。

        1、Runnable当中的this引用

        在Java当中通过实现Runnable接口创建线程的时候,this引用关键字代表实现了Runnable接口的类的实例的引用(这句话有点拗口),而不是线程对象本身,因此我们在实现了Runnable接口的类当中使用this它将引用到该类的实例,而不是代表正在执行的线程对象。

        但是在某种情况下我们可能需要获取当前正在执行的线程对象的引用,例如在多线程环境下,你想要获取当前线程的一些属性或者执行某些操作,这个时候就需要使用Thread类的静态方法currentThread()来获取当前线程的引用。

class MyRunnable implements Runnable{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        System.out.println("当前线程的名称:" + Thread.currentThread().getName());
        System.out.println("当前线程的优先级:" + thread.getPriority());
        //Thread.currentThread().getName() 两种方式等价
    }
}
public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

        在上面的例子中,通过调用Thread.currentThread()方法,我们获取了当前正在执行的线程对象的引用,并通过该引用调用了Thread类的一些方法,如getName()和getPriority()来获取线程的名称和优先级。这样就能够在Runnable接口实现类中获取到当前线程对象的引用,并对其进行操作。

        2、Thread继承类当中的this引用

        当我们继承Thread类来创建线程的时候,在线程的运行过程当中,this关键字确实代表线程对象的引用,也就是说this指向了正在执行该线程的Thread对象。

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("当前线程名称:" + this.getName());
        System.out.println("当前线程优先级:" + this.getPriority());
        System.out.println("MyThread is running");
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

        在这个例子中,当你调用myThread.start()时,系统会创建一个新的线程,并调用MyThread类的run()方法。在run()方法中,this关键字代表了当前线程对象,我们可以通过this来访问当前线程的属性和方法,比如getName()和getPriority()来获取当前线程的名称和优先级。


三、匿名内部类创建线程

        1、匿名内部类创建Thread对象

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println("MyThread is running");
            }
        };
        thread.start();
    }
}

        在这个例子当中,我们创建了一个Thread的匿名子类,并且重写了其run()方法,然后直接在main方法当中创建了这个Thread子类的对象,然后调用其start()方法启动线程,这种方式可以省略编写一个具体的Thread子类的步骤,使得代码更加简洁。

        2、匿名内部类创建Runnable子类对象

public class Main {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable is running");
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

        在这个例子中,我们创建了一个实现了Runnable接口的匿名内部类,并重写了其run()方法。然后,我们将这个匿名内部类的对象传递给了Thread类的构造方法,从而创建了一个新的线程对象。最后调用start()方法启动了线程。

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

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

相关文章

C++如何使用string类

文章目录 为什么要学习string?库中的string关于编码ASCII编码Unicode编码 迭代器Iteratorsstring常用构造接口接口声明与功能说明接口演示 string类对象的容量操作接口声明与功能说明接口演示reverse与resize在不同平台下的扩容与缩容机制 string类对象的访问及遍历操作接口声…

Java项目实现图形验证码(Hutool)

项目架构: 使用SpringCloudmysqlmybatis-plus需要将数据库中的数据导出到Excel文件中 前端为Vue2 业务场景: 登录时使用验证码登录 1.1 打开hutool, 搜索 图片验证码 1.2后端编写生产验证码方法 1.3前端 1.3.1展示验证码 1.3.2 前端方法 1.3.2.1UU…

Django中的数据库优化与ORM性能调优【第169篇—ORM性能调优】

👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Django中的数据库优化与ORM性能调优 在开发基于Django的Web应用程序时,数据库是…

ubuntu 查询mysql的用户名和密码 ubuntu查看username

ubuntu 查询mysql的用户名和密码 ubuntu查看username 文章标签mysqlUbuntu用户名文章分类MySQL数据库 一.基本命令 1.查看Ubuntu版本 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.5 LTS Release: 16.04 Coden…

leetcode-分割链表

题目 面试题 02.04. 分割链表 提示 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 示例 1: 输入&#xff…

linux-centos虚拟机设置固定ip

环境准备 虚拟机版本:centos7 安装环境:vmware17 1、设置网络连接 虚拟机-设置-网络适配器-NAT模式 2、查看子网信息 编辑-虚拟网络编辑器-NAT模式-NAT设置 查看子网ip和网关ip 下一步要用 3、修改配置文件 vim /etc/sysconfig/network-scripts…

BGP边界网关路由实验(华为)

一,技术简介 BGP(边界网关路由协议)是一种自治系统(AS)间的协议,主要用于在不同的AS之间交换路由信息。AS是一个由一组网络设备和路由器组成的网络集合,这些设备可以在一个共同的管理域中协同工…

Netty-NioServerSocketChannel与NioSocketChannel

NioServerSocketChannel NioServerSocketChannel是netty服务端的channel。在ServerbootStrap的bind方法中,通过反射,实例化对象NioServerSocketChannel。   NioServerSocketChannel对象实例化的过程中。 AbstractChannel中实例化channel的id&#xff…

【QT进阶】Qt Web混合编程之QWebEngineView基本用法

往期回顾 【QT入门】Qt自定义控件与样式设计之自定义QTabWidget实现tab在左,文本水平的效果-CSDN博客【QT进阶】Qt Web混合编程之CEF、QCefView简单介绍-CSDN博客 【QT进阶】Qt Web混合编程之VS2019 CEF的编译与使用-CSDN博客 【QT进阶】Qt Web混合编程之QWebEngi…

通过Idea部署Tomcat服务器

1.在idea中创建项目 有maven构建工具就创建maven,没有就正常创建一个普通的java程序 创建普通java项目 2.添加框架 3.配置 Tomcat 注意:创建web项目后我们需要配置tomcat才能运行,下面我们来进行配置。 4.添加部署 回到服务器 5.完善配置 6…

EFK环境搭建(基于K8S环境部署)

目录 一.环境信息二.安装nfs供应商三.安装elasticsearch四.安装kibana组件五.安装fluentd 一.环境信息 1.服务器及k8s版本 IP地址主机名称角色版本192.168.40.180master1master节点1.27192.168.40.181node1node1节点1.27192.168.40.182node2node2节点1.27 2.部署组件版本 序…

Python 数据结构和算法实用指南(二)

原文:zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者:飞龙 协议:CC BY-NC-SA 4.0 第四章:列表和指针结构 我们已经在 Python 中讨论了列表,它们方便而强大。通常情况下,我们使用 Python…

近端安全互联样例使用指导

样例介绍 本样例基于rk3568开发板,通过封装openharmony安全子系统deviceauth组件提供的能力,实现了一组可用于设备间快速建立可信认证和连接的接口,通过预先定义关系网,在设备初始化阶段完成端端设备间的认证,构建安全…

ES源码四:网络通信层流程

听说ES网络层很难?今天来卷它😄 前言 ES网络层比较复杂,分为两个部分: 基于HTTP协议的REST服务端基于TCP实现的PRC框架 插件化设计的网络层模块(NetworkModule) 入口还是上一章的创建Node构造方法的地方…

目标检测应用场景—数据集【NO.31】布匹数据集目标检测数据集

写在前面:数据集对应应用场景,不同的应用场景有不同的检测难点以及对应改进方法,本系列整理汇总领域内的数据集,方便大家下载数据集,若无法下载可关注后私信领取。关注免费领取整理好的数据集资料!今天分享…

uniapp picker 多列选择器用法

uniapp picker 多列选择器联动筛选器交互处理方法, uniapp 多列选择器 mode"multiSelector" 数据及筛选联动交互处理, 通过接口获取数据,根据用户选择当前列选项设置子列数据,实现三级联动效果, 本示例中处…

【honggfuzz学习笔记】honggfuzz的基本特性

本文架构 1.动机2.honggfuzz的基本概念官网描述解读 3. honggfuzz的反馈驱动(Feedback-Driven)软件驱动反馈(software-based coverage-guided fuzzing)代码覆盖率代码覆盖率的计量单位 代码覆盖率的统计方式 硬件驱动反馈( hardware-based co…

IDEA 安装、基本使用、创建项目

文章目录 下载基本使用修改颜色主题Keymap插件 创建项目创建模块新建 Java 类运行新建 Package打包 Jar运行 jar 包 查看文档 下载 官方下载地址:https://www.jetbrains.com/zh-cn/idea/download/?sectionmac 这里我下载 macOS 社区版,IDEA 2024.1 (C…

60道计算机二级模拟试题选择题(含答案和解析)

点击下载《60道计算机二级模拟试题选择题(含答案和解析)》 1. 前言 本文设计了一份针对计算机二级考试的选择题,旨在考察考生对计算机基础知识和应用技能的掌握情况。试题涵盖了计算机基础知识、操作系统、办公软件、计算机网络等多个方面&…

【学习】Jmeter、postman、python如何与数据库相互配合

在当今数字化时代,数据库已经成为我们日常生活中不可或缺的一部分。无论是购物、社交还是工作,数据库都在默默地为我们提供着高效、稳定的服务。而在众多的技术工具中,Jmeter、Postman和Python成为了操作数据库的三大主流技术。今天&#xff…
最新文章