线程创建和Thread类

创建一个线程的方法

创建一个线程的方法,有非常多种:

  • 继承Thread类,重写run方法。

  • 实现Runnable接口,实现run方法,然后将Runnable实例传递给Thread构造器。

  • 实现Callable接口,结合FutureTaskThread类(这是对Runnable的功能增强,用于获取返回值)。

继承Thread类

创建一个子类继承Thread类,并且重新run方法

csharp 复制代码
        Thread thread=new Thread(){
            @Override
            public void run() {
                while(true){
                    System.out.println("线程执行中...");
                }
            }
        };

实现Runnable接口

通过实现Runnable接口,重写run方法

csharp 复制代码
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println("线程执行中...");
                }

            }
        };
        Thread thread=new Thread(runnable);

实现Callable接口,并封装在FutureTask中,再放入Thread

ini 复制代码
        Callable<String> callable=new Callable<>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(2000);
                return "hello,JUC";
            }
        };
        FutureTask<String> task=new FutureTask<String>(callable);
        Thread thread=new Thread(task);
        thread.start();
        String s = task.get();
        System.out.println(s);

Thread源码解析

三种创建线程的相同点

现在来看看Thread的背后做了什么事。

typescript 复制代码
public class Thread implements Runnable {
    private Runnable target;
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
}

从上述简化的代码来看,Thread本质也是一个Runnable,并且还持有一个Runnable对象。

因此上面的几种方法都有了解释:

  1. 第一种继承Thread,直接覆写run方法的逻辑,不再使用target
  2. 第二种传入一个target,执行target中的run方法
  3. 第三种的本质也是第二种

线程启动的过程

以下是start的源码

csharp 复制代码
public synchronized void start() {

        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {

            }b
        }
    }

start方法被synchronized修饰,确保在多线程环境下,检查线程状态和启动过程是原子的,防止一个线程对象被并发启动多次。

threadStatus为0时,代表着是NEW状态,此时线程对象创建了,但是没有启动,如果threadStatus不为0,说明线程已经启动了。

通过启动加锁与检查线程状态,保证了线程不可重复启动的特性。

从代码中并没有看到run方法被调用的语句,因为真正的启动在start0

相关推荐
程序员黑豆2 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
风流 少年3 小时前
Spring AI 2.0:Memory
java·后端·spring
码匠许师傅3 小时前
【C++ 面试真题】聊聊 C++ 的移动语义与右值引用
java·c++·面试
小席是个热心肠4 小时前
AI相关的自我学习
java·人工智能·学习
数智化管理手记6 小时前
海量数据如何沉淀有效数据资产?数据标准化治理方案如何搭建?
java·大数据·人工智能
cfm_29147 小时前
SpringAI + Ollama 本地大模型
java·开发语言·人工智能·语言模型
鲸采云SRM采购管理系统8 小时前
采购管理系统哪家好?2026最新测评对比
java·服务器·数据库
0x538 小时前
Java网络编程(二)
java·服务器·网络
Flittly9 小时前
【雕虫大技】Agent 动态 Skill 供应链安全加固(三):输出校验与治理闭环实战
java·spring boot·spring
Poo_Chai9 小时前
QT emit信号后完整处理流程,包括槽函数响应流程
java·开发语言·数据库