news 2026/4/18 13:03:27

谁在调用?线程类的构造与静态块解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
谁在调用?线程类的构造与静态块解析

文章目录

  • 谁在调用?线程类的构造与静态块解析 ?
    • 线程的创建方式
      • 1. 继承Thread类的方式
      • 2. 实现Runnable接口的方式
    • 静态代码块和构造方法的区别
      • 静态代码块
      • 构造方法
    • 线程创建与静态代码块的结合
      • 案例1:静态代码块在多线程环境下的执行情况
      • 案例2:静态代码块中的多线程问题
    • 结论
    • 因此,在编写多线程程序时,我们需要特别注意静态代码块和构造方法的区别,避免在不合适的地方启动线程或者执行其他敏感的操作。
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

谁在调用?线程类的构造与静态块解析 ?

大家好,闫工又和大家见面了!今天咱们要聊的主题有点意思,是关于Java中的线程创建方式以及静态代码块的执行时机。这个问题看似简单,但其中涉及的知识点可不少,而且很容易让人掉进一些“坑”里。所以,今天的分享,我会结合实际案例,详细解析这两个知识点,并且带大家一起来看看“谁在调用”。

线程的创建方式

说到线程的创建,Java中主要有两种方式:继承Thread类和实现Runnable接口。除此之外,还有第三种方式,那就是通过Callable接口来实现更复杂的任务处理。不过,今天我们主要围绕前两种方式进行讨论。

1. 继承Thread类的方式

这种方式应该是大家最熟悉的了。继承Thread类之后,我们需要重写run()方法,并在适当的时候调用start()方法来启动线程。代码大致如下:

classMyThreadextendsThread{@Overridepublicvoidrun(){System.out.println("闫工说:我在执行任务!");}}publicclassMainClass{publicstaticvoidmain(String[]args){MyThreadthread=newMyThread();thread.start();// 启动线程,调用run方法}}

这里有个细节需要注意,那就是start()方法和run()方法的区别。start()方法会启动一个新的线程,并在该线程中执行run()方法;而直接调用run()方法,则是使用当前的主线程来执行任务,这样并没有实现多线程的效果。

2. 实现Runnable接口的方式

相比于继承Thread类,实现Runnable接口的方式更加灵活。因为Java只支持单继承,所以如果我们已经继承了其他类,就无法再通过继承Thread类的方式来创建线程了。这时候,实现Runnable接口就是更好的选择。

classMyRunnableimplementsRunnable{@Overridepublicvoidrun(){System.out.println("闫工说:我在执行任务!");}}publicclassMainClass{publicstaticvoidmain(String[]args){MyRunnablerunnable=newMyRunnable();Threadthread=newThread(runnable);thread.start();// 启动线程,调用run方法}}

这种方式的好处在于,我们可以将任务逻辑封装在Runnable接口的实现类中,而线程的管理则由Thread类来完成。不过,有一点需要注意的是,在Thread类的构造函数中,我们传入了一个实现了Runnable接口的对象,这样Thread类才会知道如何执行我们的任务。

静态代码块和构造方法的区别

好了,现在回到今天的主题,“谁在调用?”其实这个问题主要涉及到静态代码块和构造方法的区别。在Java中,静态代码块是在类加载时就会被执行的,而构造方法则是每次创建对象时才会被调用的。

静态代码块

静态代码块是写在类中的一个特殊结构,它会被JVM在类第一次被加载的时候执行。需要注意的是,静态代码块只会在类被加载时执行一次,无论这个类被实例化多少次。

classStaticBlock{static{System.out.println("闫工说:静态代码块被执行了!");}}publicclassMainClass{publicstaticvoidmain(String[]args){// 只要MainClass被加载,StaticBlock也会被加载newStaticBlock();}}

构造方法

构造方法是在创建对象时调用的,每次创建对象都会执行一次。

classConstructorExample{publicConstructorExample(){System.out.println("闫工说:构造方法被执行了!");}}publicclassMainClass{publicstaticvoidmain(String[]args){newConstructorExample();// 第一次调用构造方法newConstructorExample();// 第二次调用构造方法}}

线程创建与静态代码块的结合

现在,我们来看看线程创建和静态代码块之间有什么关联。其实,在某些情况下,如果我们不注意静态代码块的使用,可能会导致一些意想不到的结果。

案例1:静态代码块在多线程环境下的执行情况

假设我们有一个类MyThread,它继承了Thread类,并且在这个类中定义了一个静态代码块和一个构造方法:

classMyThreadextendsThread{static{System.out.println("闫工说:静态代码块被执行了!");}publicMyThread(){System.out.println("闫工说:构造方法被执行了!");}@Overridepublicvoidrun(){System.out.println("闫工说:线程在执行任务!");}}publicclassMainClass{publicstaticvoidmain(String[]args){newMyThread().start();newMyThread().start();}}

运行这段代码,控制台会输出什么呢?我们来分析一下:

  1. MainClass被执行时,首先会加载MyThread类。在类加载的时候,静态代码块会被执行一次,输出“闫工说:静态代码块被执行了!”。
  2. 然后,在主线程中创建第一个MyThread对象,这时候构造方法被调用,输出“闫工说:构造方法被执行了!”。
  3. 调用start()方法,启动线程,执行run()方法,输出“闫工说:线程在执行任务!”。
  4. 接着,创建第二个MyThread对象,同样会调用构造方法,输出“闫工说:构造方法被执行了!”。
  5. 再次调用start()方法,启动另一个线程,执行run()方法。

所以,最终的输出结果应该是:

闫工说:静态代码块被执行了! 闫工说:构造方法被执行了! 闫工说:线程在执行任务! 闫工说:构造方法被执行了! 闫工说:线程在执行任务!

通过这个案例,我们可以看到静态代码块只会在类加载时被调用一次,而构造方法则会随着对象的创建而多次被调用。

案例2:静态代码块中的多线程问题

有时候,我们可能会不小心在静态代码块中启动线程,这样可能会导致一些意想不到的问题。例如:

classMyThreadextendsThread{static{newMyThread().start();// 在静态代码块中启动线程System.out.println("闫工说:静态代码块被执行了!");}publicMyThread(){System.out.println("闫工说:构造方法被执行了!");}@Overridepublicvoidrun(){System.out.println("闫工说:线程在执行任务!");}}publicclassMainClass{publicstaticvoidmain(String[]args){newMyThread().start();}}

这段代码可能会引发一些问题。因为当MyThread类被加载时,静态代码块会被执行,从而创建并启动一个线程。然而,在这个过程中,我们可能还没有准备好处理这个额外的线程。

运行这段代码,控制台会输出:

  1. 静态代码块被执行,构造方法被执行一次,然后启动线程。
  2. 主线程继续执行,创建另一个MyThread对象,并启动它。

所以,最终的输出可能是这样的:

闫工说:构造方法被执行了! 闫工说:线程在执行任务! 闫工说:静态代码块被执行了! 闫工说:构造方法被执行了! 闫工说:线程在执行任务!

但是,这里有一个问题。在静态代码块中创建并启动了一个MyThread对象,这可能会导致一些竞态条件或者资源竞争的问题,尤其是在多线程环境下。

结论

通过以上的分析和案例,我们可以得出以下结论:

  1. 静态代码块是在类加载时被执行的,只执行一次。
  2. 构造方法是每次创建对象时被调用的,可能会被多次调用。
  3. 在静态代码块中启动线程需要特别小心,以免引发不可预测的问题。

因此,在编写多线程程序时,我们需要特别注意静态代码块和构造方法的区别,避免在不合适的地方启动线程或者执行其他敏感的操作。

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 23:48:06

实战AKShare股票接口修复:快速解决数据异常终极指南

实战AKShare股票接口修复:快速解决数据异常终极指南 【免费下载链接】aktools AKTools is an elegant and simple HTTP API library for AKShare, built for AKSharers! 项目地址: https://gitcode.com/gh_mirrors/ak/aktools 在量化投资和金融数据处理的日常…

作者头像 李华
网站建设 2026/4/17 16:59:59

AI手势识别摄像头实时接入:从静态图到视频流升级实战

AI手势识别摄像头实时接入:从静态图到视频流升级实战 1. 引言:从图像识别到动态交互的跨越 1.1 手势识别的技术演进与现实需求 随着人机交互方式的不断演进,传统的键盘、鼠标、触控操作已无法满足日益增长的沉浸式体验需求。在智能硬件、虚…

作者头像 李华
网站建设 2026/4/16 12:26:09

MediaPipe Hands教程:手部姿态估计从入门到精通

MediaPipe Hands教程:手部姿态估计从入门到精通 1. 引言:AI 手势识别与追踪 随着人机交互技术的不断发展,手势识别正逐渐成为智能设备、虚拟现实、增强现实乃至智能家居的核心交互方式之一。相比传统的触控或语音输入,手势控制更…

作者头像 李华
网站建设 2026/4/17 18:07:16

原神抽卡记录全解析:从数据获取到深度分析的一站式解决方案

原神抽卡记录全解析:从数据获取到深度分析的一站式解决方案 【免费下载链接】genshin-wish-export biuuu/genshin-wish-export - 一个使用Electron制作的原神祈愿记录导出工具,它可以通过读取游戏日志或代理模式获取访问游戏祈愿记录API所需的authKey。 …

作者头像 李华
网站建设 2026/4/16 19:25:06

从零开始部署AI手势识别模型:Hands追踪完整指南

从零开始部署AI手势识别模型:Hands追踪完整指南 1. 引言 1.1 AI 手势识别与追踪 在人机交互日益智能化的今天,手势识别正成为连接人类意图与数字系统的核心桥梁。从智能穿戴设备到虚拟现实(VR)、增强现实(AR&#x…

作者头像 李华
网站建设 2026/4/17 8:51:23

MediaPipe Hands部署教程:无需GPU的高精度手部追踪方案

MediaPipe Hands部署教程:无需GPU的高精度手部追踪方案 1. 引言:AI手势识别与交互的新可能 随着人机交互技术的不断演进,手势识别正逐步成为智能设备、虚拟现实、增强现实乃至工业控制中的关键感知能力。传统的触摸或语音交互方式在特定场景…

作者头像 李华