Java线程创建的5种写法详解

 更新时间:2026年05月31日 09:32:45   作者:ChaoYLuo  
这段文章详细解释了线程与进程的关系、线程状态、线线程创建的几种写法、常见面试题以及高耦合与低耦合的概念,通过这些内容,读者可以全面了解线程的基础知识及其在编程中的应用,需要的朋友可以参考下

一、多线程基础概念

1. 线程与进程的关系

  • 线程是轻量级进程,进程是重量级进程
  • 进程是操作系统资源分配的基本单位,线程是操作系统调度执行的基本单位
  • 进程之间不会相互影响,但线程可能会相互影响(因为线程共享进程资源)。
  • 进程内部包含线程,同一个进程的多个线程之间共享同一份资源
  • 线程创建不需要申请资源,销毁也不需要释放资源(相比进程开销小)。
  • CPU发展瓶颈 → 多核心(多线程充分利用多核)。

2. 线程状态:Thread.sleep(millis: 1000)

  • sleep让当前线程进入阻塞状态(暂停执行指定时间)。

3. 方法重写要求

  • 父类方法和子类方法,签名完全一致(包括:方法名、参数列表、声明的抛出异常...)。

二、线程创建的几种写法

写法1:继承Thread,重写run

class MyThread extends Thread {
    @Override
    public void run() {
        while (true) {
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

写法2:实现Runnable,搭配Thread执行

// 1. 定义 Runnable 实现类
class MyRunnable implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

// 2. 创建线程
public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start(); // 启动新线程,执行 Runnable 内部的 run
        
        while (true) {
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}
  • Runnable自身一般不会单独执行,需要搭配“载体”(Thread)执行。
  • 不再需要重写 run(已实现在 Runnable中)。
  • 本质:启动的新线程会执行 Runnable内部的 run方法。

写法3:继承Thread,使用匿名内部类

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start(); // 记住:调用 start 才是真正创建线程
        
        while (true) {
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

步骤:

  1. 创建 Thread的子类(匿名内部类,无名字)。
  2. 重写 run
  3. 创建 Thread子类的实例,并用 t引用指向。

特点:方便、一次性使用。

写法4:实现Runnable,使用匿名内部类

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        t.start();
        
        while (true) {
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}
  • 此处针对 Runnable定义匿名内部类,返回结果是一个 Runnable的引用,把这个引用传入 Thread

写法5:【简化】lambda表达式

public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (true) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.start();
        
        while (true) {
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}
  • 数据结构角度来看:枚举、lambda、反射。
  • lambda本质上是一个“匿名函数”,很多地方都能支持。
  • Java 语法非常死板,必须得有类;最初 Java 和其他语言都有 lambda,先搞了个匿名内部类过渡。
  • 函数式接口(如 Runnable是函数式接口)。

三、常见面试题:Thread对象与start()的关系

问题:多次调用start()会怎样?

public static void main(String[] args) {
    Thread thread = new Thread(() -> {
        System.out.println("hello");
    });
    thread.start();
    thread.start(); // 报错!
    thread.start();
}
  • 报错:java.lang.IllegalThreadStateException: Thread already started
  • 原因:Java 约定,一个 Thread对象,和一个操作系统中的线程是“一一对应”关系
  • 因此,一个 Thread对象,只能 start一次
  • 后续学习 Thread上的其他方法/属性,都是控制这个对应系统中的线程。

四、补充:高耦合 vs 低耦合(生活类比)

  • 高耦合:女朋友生病了,我推掉所有工作,全身心在医院照顾 → 假设陌生人生病了,对我没啥影响,朋友圈点赞之交,该干啥干啥,影响非常小。
  • 低耦合:任务(Runnable)和线程(Thread)解耦 → 任务和线程概念绑定(继承 Thread)时,若改成其他形式,需要大规模修改代码;而 Runnable没有和线程概念绑定,任务可方便地迁移到其他载体上。

五、包(package)的概念

  • Java 中类太多(标准库、第三方库、自己写的)→ 乱。
  • 包:一组有关系的类放到一起
  • 包默认情况下不会引入到代码中,使当前代码引入的类比较少、不容易乱。
  • import java.util.*;:导入包中所有类(不推荐)。
  • 最基础常用的:import java.lang.*(默认导入)。

以上就是Java线程创建的5种写法详解的详细内容,更多关于Java线程创建写法的资料请关注脚本之家其它相关文章!

相关文章

  • SpringMVC中redirect重定向(带参数)的3种方式

    SpringMVC中redirect重定向(带参数)的3种方式

    Spring MVC中做form表单功能提交时,防止用户客户端后退或者刷新时重复提交问题,需要在服务端进行重定向跳转,本文主要介绍了SpringMVC中redirect重定向(带参数)的3种方式,感兴趣的可以了解一下
    2024-07-07
  • Java日期时间使用方法汇总

    Java日期时间使用方法汇总

    这篇文章主要针对Java日期时间使用方法进行汇总,感兴趣的朋友可以参考一下
    2016-03-03
  • Java平台调试体系原理分析和实践整理 远程Debug

    Java平台调试体系原理分析和实践整理 远程Debug

    这篇文章主要介绍了Java平台调试体系原理分析和实践整理 远程Debug,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

    SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

    这篇文章主要给大家介绍了关于SpringMVC实现文件上传与下载、拦截器、异常处理器等功能的相关资料,这些功能在我们日常开发中经常会遇到,本文通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-09-09
  • mybatis动态新增(insert)和修改(update)方式

    mybatis动态新增(insert)和修改(update)方式

    这篇文章主要介绍了mybatis动态新增(insert)和修改(update)方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • springboot中设置定时任务的三种方法小结

    springboot中设置定时任务的三种方法小结

    在我们开发项目过程中,经常需要定时任务来帮助我们来做一些内容,本文介绍了springboot中设置定时任务的三种方法,主要包括@Scheduled注解,Quartz框架和xxl-job框架的实现,感兴趣的可以了解一下
    2023-12-12
  • java制作复制文件工具代码分享

    java制作复制文件工具代码分享

    如果目标位置没有同名文件,则直接拷贝过去;如果目标位置已有同名文件,则比对文件的最后修改日期,来进行覆盖或者忽略。程序会在可以在复制过程中自动创建目录,并生成log文件,创建了哪些目录、文件,覆盖了哪些文件、跳过了哪些文件,文件的时间、位置等信息都一目了然
    2014-01-01
  • Java redisTemplate阻塞式处理消息队列

    Java redisTemplate阻塞式处理消息队列

    用redis中的List可以实现队列,这样可以用来做消息处理和任务调度的队列。因此,本文将主要为大家介绍如何利用redisTemplate处理消息队列,感兴趣的小伙伴可以了解一下
    2021-12-12
  • Spring Boot 声明式调用 Feign 从入门到精通实例详解

    Spring Boot 声明式调用 Feign 从入门到精通实例详解

    这篇文章给大家介绍Spring Boot声明式调用Feign从入门到精通实例详解,本文全面介绍了Feign的使用和配置,涵盖基础和高级特性,以及在复杂场景中的应用,感兴趣的朋友跟随小编一起看看吧
    2026-04-04
  • 解读nacos获取配置文件的大致过程

    解读nacos获取配置文件的大致过程

    这篇文章主要介绍了nacos获取配置文件的大致过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07

最新评论