【JAVA-Day77】Java线程继承Thread类实现Runnable接口

Java线程继承Thread类实现Runnable接口

  • 《Java线程编程指南:轻松掌握线程的创建和启动》
    • 摘要 😊
    • 引言 🚀
      • 一、什么是进程和线程 ❓
      • 二、线程如何创建 😎
        • 2.1 继承Thread类并重写run()方法 📝
        • 2.2 实现Runnable接口并实现run()方法 💡
      • 三、线程如何启动 🚀
      • 四、线程的应用场景 🌐
      • 五、线程面试题 💬
      • 六、总结 📌
    • 参考资料 📚

在这里插入图片描述

博主 默语带您 Go to New World.
个人主页—— 默语 的博客👦🏻
《java 面试题大全》
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨


《Java线程编程指南:轻松掌握线程的创建和启动》

摘要 😊

作为Java博主,想要让你轻松掌握线程的创建和启动,本文将详细介绍线程的概念、创建方法、启动方式以及常见应用场景,同时还包括一些有趣的面试题。让我们一起深入探讨,让线程编程变得简单有趣!

引言 🚀

在Java编程中,线程是一个至关重要的概念。了解如何创建和启动线程是每个Java程序员的基本功。本文将为您详细介绍线程的创建方式,并通过丰富的代码案例演示,带您深入理解。

一、什么是进程和线程 ❓

进程和线程是操作系统中重要的概念,它们都是用来管理和执行程序的方式。在计算机科学中,进程(Process)是指正在运行的一个程序的实例,它包括了程序的代码、数据和程序执行时所需的系统资源。而线程(Thread)是进程中的一个独立执行单元,一个进程可以拥有多个线程,这些线程共享了进程的资源,包括内存空间、文件句柄等,但每个线程拥有自己的执行路径和局部变量。相比于进程,线程更加轻量级,创建和切换的开销更小,因此可以更高效地实现并发执行和资源共享。

二、线程如何创建 😎

在Java中,线程的创建有两种常见方式:继承Thread类和实现Runnable接口。接下来我们将分别介绍这两种方式。

2.1 继承Thread类并重写run()方法 📝

继承Thread类并重写run()方法是一种创建线程的简单方式。下面是一个示例代码:

public class MyThread extends Thread {
    public void run() {
        // 线程执行的任务
        System.out.println("线程执行任务");
    }

    public static void main(String[] args) {
        // 创建线程对象
        MyThread myThread = new MyThread();
        // 启动线程
        myThread.start();
    }
}

在这个示例中,MyThread类继承了Thread类,并重写了run()方法来定义线程执行的任务。在main()方法中,创建了一个MyThread对象,并调用start()方法启动线程。一旦线程启动,run()方法中的任务就会在新的线程中执行。

2.2 实现Runnable接口并实现run()方法 💡

通过实现Runnable接口并实现其中的run()方法,可以创建线程的另一种方式。这种方式更加灵活,因为Java不支持多重继承,但是可以实现多个接口。下面是一个示例代码:

public class MyRunnable implements Runnable {
    public void run() {
        // 线程执行的任务
        System.out.println("线程执行任务");
    }

    public static void main(String[] args) {
        // 创建一个实现了Runnable接口的对象
        MyRunnable myRunnable = new MyRunnable();
        // 创建线程对象,并将Runnable对象作为参数传递给Thread类的构造方法
        Thread thread = new Thread(myRunnable);
        // 启动线程
        thread.start();
    }
}

在这个示例中,MyRunnable类实现了Runnable接口,并实现了其中的run()方法。在main()方法中,创建了一个MyRunnable对象,并将其作为参数传递给Thread类的构造方法来创建线程对象。然后调用线程对象的start()方法启动线程,线程执行的任务就是run()方法中定义的内容。

三、线程如何启动 🚀

在Java中,要启动一个线程,你可以通过调用线程对象的start()方法来实现。这个方法会使得新线程开始执行它的任务,具体步骤如下:

  1. 创建一个线程对象,可以通过继承Thread类并重写run()方法,或者实现Runnable接口并实现其中的run()方法来创建线程对象。
  2. 调用线程对象的start()方法。这个方法会告诉Java虚拟机启动线程,并在新的线程中执行run()方法中的任务。

以下是一个示例代码:

public class Main {
    public static void main(String[] args) {
        // 继承Thread类的方式创建线程
        MyThread myThread = new MyThread();
        myThread.start();

        // 实现Runnable接口的方式创建线程
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

在这个示例中,MyThreadMyRunnable分别是通过继承Thread类和实现Runnable接口的方式创建的线程。通过调用start()方法,这些线程就会启动并执行它们的任务。

四、线程的应用场景 🌐

线程在Java编程中的应用场景非常广泛,主要包括以下几个方面:

  1. 多线程下载: 在网络编程中,使用多线程可以实现文件的多线程下载,加快下载速度。每个线程负责下载文件的一部分,从而充分利用带宽资源。


    在网络编程中,使用多线程进行文件的多线程下载可以显著提高下载速度,尤其是对于大文件或者带宽较大的网络环境。这种方法充分利用了带宽资源,将文件分成多个部分,每个线程负责下载其中的一部分,然后将这些部分合并成完整的文件。具体步骤如下:

    1. 确定文件大小和分块大小: 首先确定要下载的文件的大小,并确定每个线程下载的分块大小。通常情况下,可以将文件平均分成若干个分块,每个分块大小相同或者差不多。

    2. 创建多个线程: 根据文件的分块数,创建相应数量的线程。每个线程负责下载文件的一个分块。

    3. 指定下载范围: 每个线程需要知道自己下载的文件范围,即从哪个字节开始下载,到哪个字节结束。可以通过设置HTTP请求的Range头部来指定下载范围。

    4. 并发下载: 启动所有线程,让它们并发执行。每个线程根据自己负责的下载范围发送HTTP请求,下载文件的对应部分。

    5. 合并文件: 所有线程下载完成后,将它们下载的文件部分合并成完整的文件。可以通过文件操作来实现文件的合并,将每个分块按照顺序写入到最终的文件中。

    需要注意的是,在实现多线程下载时,还需要考虑线程安全、异常处理、断点续传等问题,确保下载过程稳定可靠。另外,为了避免对服务器造成过大的压力,下载线程的数量需要适当控制。

  2. 并发处理: 在需要处理大量任务的情况下,使用多线程可以并发处理任务,提高程序的处理效率。例如,在Web服务器中,每个请求可以由一个独立的线程来处理,从而支持同时处理多个请求。


    在需要处理大量任务的情况下,使用多线程可以实现并发处理,从而提高程序的处理效率。这在很多场景下都是非常有用的,比如在Web服务器中。

    在Web服务器中,每个客户端请求可以由一个独立的线程来处理,这意味着服务器可以同时处理多个请求,而不必等待每个请求都处理完成才能处理下一个请求。具体来说,当一个请求到达服务器时,服务器会创建一个新的线程来处理这个请求,然后继续监听其他请求。这样就可以支持同时处理多个请求,提高了服务器的并发能力和响应速度。

    通过多线程并发处理请求,可以充分利用服务器的资源,提高系统的吞吐量和响应性能。但需要注意的是,在并发处理中,需要考虑线程安全和资源竞争等问题,确保多个线程能够正确地共享资源,并且不会出现数据不一致或者死锁等情况。

    总的来说,使用多线程进行并发处理可以提高程序的处理效率,特别是在需要处理大量任务的情况下,可以充分利用系统资源,提高系统的并发能力和性能。

  3. 线程池: 线程池是一种管理线程的机制,它可以重用已创建的线程,减少线程创建和销毁的开销,提高系统的性能和稳定性。通过线程池,可以控制并发执行的线程数量,防止系统因为线程过多而资源耗尽。


    线程池是一种管理线程的机制,它可以重用已创建的线程,减少线程创建和销毁的开销,从而提高系统的性能和稳定性。通过线程池,可以控制并发执行的线程数量,防止系统因为线程过多而资源耗尽。

    使用线程池的主要好处包括:

    1. 降低资源消耗: 线程池可以重用已创建的线程,避免频繁地创建和销毁线程所带来的资源消耗,从而减少系统的开销。

    2. 提高响应速度: 由于线程池中已经预先创建了一定数量的线程,可以更快地响应任务的到来,减少任务等待的时间。

    3. 控制并发度: 可以通过调整线程池的大小来控制并发执行的线程数量,避免系统因为线程过多而资源耗尽,导致系统的性能下降或者崩溃。

    4. 统一管理: 线程池提供了统一的管理接口,可以方便地监控线程的运行状态、调整线程池的大小、设置线程池的参数等。

    Java提供了java.util.concurrent包中的Executor框架来支持线程池的实现,其中常用的实现类包括ThreadPoolExecutorScheduledThreadPoolExecutor等。通过这些类,可以方便地创建和管理线程池,提高程序的性能和稳定性。

    总的来说,线程池是一种重要的并发编程工具,在需要处理大量任务的情况下,使用线程池可以有效地管理和调度线程,提高系统的性能和响应速度。

  4. GUI编程: 在图形用户界面(GUI)编程中,使用多线程可以实现响应性更好的用户界面。例如,在Swing或JavaFX中,主线程负责用户界面的渲染和事件处理,而后台线程可以处理耗时的任务,避免阻塞主线程导致界面卡顿。


    在图形用户界面(GUI)编程中,使用多线程可以实现更好响应性的用户界面。在Swing或JavaFX等GUI框架中,主线程负责用户界面的渲染和事件处理,而后台线程可以处理耗时的任务,从而避免阻塞主线程导致界面卡顿的情况发生。

    具体来说,GUI编程中主要涉及两个线程:

    1. 主线程(UI线程): 主线程负责处理用户界面的渲染和用户交互事件,例如绘制UI组件、响应用户的鼠标点击和键盘输入等。这个线程是GUI框架内部自动创建和管理的,通常称为UI线程。

    2. 后台线程: 后台线程负责执行耗时的任务,例如从网络或文件系统中读取数据、进行复杂的计算或者与数据库进行交互等。这些任务可能会阻塞主线程,导致界面无法及时响应用户的操作,因此需要在后台线程中执行,避免影响用户体验。

    通过使用多线程,在GUI编程中可以实现以下优势:

    • 提高响应性: 后台线程负责处理耗时任务,主线程可以保持响应性,及时响应用户的操作,提高用户体验。

    • 避免界面卡顿: 将耗时任务放在后台线程中执行,避免阻塞主线程,从而避免界面卡顿或者假死的情况发生。

    • 提高系统性能: 通过合理地利用多线程,可以提高系统的处理效率和性能,更好地满足用户的需求。

    总的来说,使用多线程可以提高GUI编程的响应性和性能,但需要注意线程安全和UI更新等问题,确保多线程编程的稳定性和可靠性。

  5. 定时任务: 使用多线程可以实现定时任务的调度和执行。例如,可以使用ScheduledExecutorService来创建一个定时线程池,执行周期性的任务。


    在Java中,使用多线程可以方便地实现定时任务的调度和执行。其中,ScheduledExecutorService是一个常用的工具类,可以用来创建一个定时线程池,执行周期性的任务。

    下面是一个简单的示例代码,演示了如何使用ScheduledExecutorService来执行定时任务:

    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class ScheduledTaskExample {
        public static void main(String[] args) {
            // 创建一个定时线程池,可根据需要设置线程数量
            ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    
            // 延迟1秒后执行任务,并且每隔3秒执行一次
            executor.scheduleAtFixedRate(() -> {
                System.out.println("执行任务:" + System.currentTimeMillis());
            }, 1, 3, TimeUnit.SECONDS);
    
            // 等待一段时间,让任务执行一段时间
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // 关闭线程池
            executor.shutdown();
        }
    }
    

    在这个示例中,首先通过Executors.newScheduledThreadPool(1)创建了一个定时线程池,线程池中有1个线程。然后使用scheduleAtFixedRate()方法安排一个定时任务,该任务会在延迟1秒后开始执行,并且每隔3秒执行一次。最后,通过调用shutdown()方法关闭线程池。

    使用ScheduledExecutorService可以方便地实现定时任务的调度和执行,而且相比于使用Timer类,它具有更好的灵活性和扩展性。

总的来说,合理地利用线程可以提高程序的效率和性能,但同时也需要注意线程安全和资源竞争等问题,确保多线程的应用能够正常运行并发挥作用。

五、线程面试题 💬

这些是很常见的线程面试题,我可以为每个问题提供简洁的答案:

  1. 什么是线程?如何创建线程?

    • 线程是程序中执行的单元,它是操作系统能够进行运算调度的最小单位。在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。
  2. Thread类和Runnable接口有什么区别?

    • 继承Thread类是一种创建线程的方式,它限制了单继承的特性,但更简单直接;而实现Runnable接口则更加灵活,允许多个接口的实现。
  3. 如何安全地结束一个线程的执行?

    • 可以通过设置一个标志位来控制线程的执行状态,当标志位为true时,线程继续执行;当标志位为false时,线程退出执行。
  4. 什么是线程安全?如何保证线程安全?

    • 线程安全是指多个线程访问共享资源时不会出现数据错误或不一致的情况。可以通过使用同步机制(如synchronized关键字)、使用线程安全的数据结构(如ConcurrentHashMap、CopyOnWriteArrayList等)以及避免共享状态等方式来保证线程安全。

六、总结 📌

通过本文的学习,相信你已经掌握了线程的创建和启动方法,并了解了线程在Java编程中的应用场景。继续深入学习和实践,你会发现线程编程并不难,甚至可以带来乐趣和挑战!

参考资料 📚

  • Java线程:https://docs.oracle.com/javase/tutorial/essential/concurrency/
  • 《Java并发编程实战》
  • 《Java并发编程的艺术》

通过本文的阅读,相信你已经对Java线程编程有了更深入的理解。继续学习,不断实践,你会成为一名优秀的Java程序员!👨‍💻

在这里插入图片描述


🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

在这里插入图片描述

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

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

相关文章

jvm 内存模型介绍

一、类加载子系统 1、类加载的过程:装载、链接、初始化,其中,链接又分为验证、准备和解析 装载:加载class文件 验证:确保字节流中包含信息符合当前虚拟机要求 准备:分配内存,设置初始值 解析&a…

Protégé pizza 03 Install Protege - 本体编辑器 Ontology Editor

Protege是一款非常方便使用的开源的本体(ontology)编辑器,可以用来建立知识图谱。 这个视频介绍了Protege工具的安装,是学习pizza.owl系列知识的前提。 https://v.youku.com/v_show/id_XNjE1NDc0NTU3Mg.html

【JAVA】计算机软件工程人工智能研究生复试资料整理

1、JAVA 2、计算机网络 3、计算机体系结构 4、数据库 5、计算机租场原理 6、软件工程 7、大数据 8、英文 自我介绍 1. Java 1. == 和 equals的区别 比较基本数据类型是比较的值,引用数据类型是比较两个是不是同一个对象,也就是引用是否指向同 一个对象,地址是否相同,equ…

精读Relational Embedding for Few-Shot Classification (ICCV 2021)

Relational Embedding for Few-Shot Classification (ICCV 2021) 一、摘要 该研究提出了一种针对少样本分类问题的新方法,通过元学习策略来学习“观察什么”和“在哪里关注”。这种方法依赖于两个关键模块:自相关表示(SCR)和交叉…

OS内存管理

内存 定义 内存是计算机用于存储数据和程序的硬件设备,它允许计算机快速读取和写入数据。内存通常是临时存储,其内容在计算机关闭或断电时会丢失。内存可存放数据。程序执行前需要先放到内存中才能被CPU处理(缓和CPU与硬盘之间的速度矛盾)。 在多道程…

ZBX_NOTSUPPORTED: Unsupported item key. 原因排查

进行自定义监控项时,在zabbix-agent端测试没问题,却在zabbix-server进行测试时,出现 ZBX_NOTSUPPORTED: Unsupported item key. 1.在zabbix-agent测试没问题,证明自定义监控项的脚本没问题,却在zabbix-server端测试出…

表的连接

目录 内连接实现效果 使用左外连接,将所有的员工信息都显示出来,即便他没有对应的部门 使用右外连接,将所有的部门信息都显示出来 查询每个员工的编号、姓名、职位,以及所在各部门的领导姓名、领导职位 确定所需要的数据表 确…

IMX6ULL移植U-Boot 2022.04

目录 目录 1.编译环境以及uboot版本 2.默认编译测试 3.uboot中新增自己的开发板 3.编译测试 4.烧录测试 5.patch文件 1.编译环境以及uboot版本 宿主机Debian12u-boot版本lf_v2022.04 ; git 连接GitHub - nxp-imx/uboot-imx: i.MX U-Boot交叉编译工具gcc-arm-10.3-2021.0…

机器学习:卷积介绍及代码实现卷积操作

传统卷积运算是将卷积核以滑动窗口的方式在输入图上滑动,当前窗口内对应元素相乘然后求和得到结果,一个窗口一个结果。相乘然后求和恰好也是向量内积的计算方式,所以可以将每个窗口内的元素拉成向量,通过向量内积进行运算&#xf…

关于nuclei-ai-extension

nuclei-ai-extension 🍁 Nuclei 官方开发的 利用 AI 生成 nuclei 模板的工具。Nuclei AI - 用于快速生成 Nuclei 模板的浏览器扩展,Nuclei AI Browser Extension建立在 cloud.projectdiscovery.io 之上,使用户能够从任何网页中提取漏洞信息&…

设计模式之创建型模式

创建型模式提供创建对象的机制,能够提升已有代码的灵活性和复用性 常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。 不常用的有:原型模式。 4.1 单例模式 创建型模式提供创建对象的机制,能够提升已有代码的灵…

【MATLAB】在图框中加箭头文本注释

1、在图框中加 文本方法 —— text()函数 2、使用箭头标注——annotation()函数 X、Y是箭头的位置相对于整个方框的比例, [0.32,0.5]是指:x坐标从整个图形32%的地方到50%的地方(从左到右&…

基于laravel开发的开源交易所源码|BTC交易所/ETH交易所/交易所/交易平台/撮合交易引擎

开源交易所,基于Laravel开发的交易所 | BTC交易所 | ETH交易所 | 交易所 | 交易平台 | 撮合交易引擎。本项目有完整的撮合交易引擎源码、后台管理(后端前端)、前台(交易页面、活动页面、个人中心等)、安卓APP源码、苹果…

【蓝桥杯单片机入门记录】认识单片机

目录 单片机硬件平台 单片机的发展过程 单片机开发板 单片机基础知识 电平 数字电路中只有两种电平:高和低 二进制(8421码) 十六进制 二进制数的逻辑运算 “与” “或” “异或” 标准C与C51 如何学好单片机 端正学习的态度、培…

BUGKU-WEB 矛盾

题目描述 进入场景看看: 代码如下: $num$_GET[num]; if(!is_numeric($num)) { echo $num; if($num1) echo flag{**********}; }解题思路 需要读懂一下这段PHP代码的意思明显是一道get相关的题目,需要提供一个num的参数,然后需要传入一个不…

CSGO搬砖项目怎么样?分享一下个人的看法!

对于steam搬砖平台,无人不知,无人不晓啊,全球最大的一个游戏平台,像我们知道的PUBG,CS:GO,都是里面的,比较火的一个平台。 对于想了解Steam搬砖的,今天分享一下个人的看法。 首先&a…

【C语言】数据结构#实现堆

目录 (一)堆 (1)堆区与数据结构的堆 (二)头文件 (三)功能实现 (1)堆的初始化 (2)堆的销毁 (3)插入数据 …

java中stream流中的concat合并操作

可以用stream.of来合并两个流 public class Test7concat {public static void main(String[] args) {/*Stream流:static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);合并2个流中的元素*/Stream<String> stream1 St…

石子合并+环形石子合并+能量项链+凸多边形的划分——区间DP

一、石子合并 (经典例题) 设有 N 堆石子排成一排&#xff0c;其编号为 1,2,3,…,N。 每堆石子有一定的质量&#xff0c;可以用一个整数来描述&#xff0c;现在要将这 N 堆石子合并成为一堆。 每次只能合并相邻的两堆&#xff0c;合并的代价为这两堆石子的质量之和&#xff0c;…

python系统学习Day2

section3 python Foudamentals part one&#xff1a;data types and variables 数据类型&#xff1a;整数、浮点数、字符串、布尔值、空值 #整型&#xff0c;没有大小限制 >>>9 / 3 #3.0 >>>10 // 3 #3 地板除 >>>10 % 3 #1 取余#浮点型&#xff…