线程创建和Thread类

创建一个线程的方法

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

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

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

  • 实现Callable接口,结合FutureTask和Thread类(这是对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 分钟前
【BFS 解决拓扑排序】火星词典
java·算法·leetcode·广度优先·宽度优先·图搜索算法
霸道流氓气质2 分钟前
Java调用StableDiffusion/ComfyUI图像生成:DAG工作流编排、WebSocket实时进度与Flux模型集成的生产级实战
java·websocket·stable diffusion
北风toto13 分钟前
KMP 算法详解:从暴力匹配到 O(n+m) 的字符串搜索
java·开发语言·算法
weixin1997010801614 分钟前
《京东JOS API:落地方案、接口边界与业务踩坑 —— 联盟免费 vs 商家按量的双轨制》(附python源码)
java·网络·python
衡石科技16 分钟前
从语义准备到模型验收:HENGSHI SENSE Data Agent 的 RAG 与部署工程实践
java·大数据·人工智能·数据分析·rag
G018_star sky♬17 分钟前
java学习日记-多态与好玩的写法
java
撸串-研究生19 分钟前
面向景区的综合服务管理平台设计——以稻城亚丁景区为例【附源码】
java·开发语言·vue.js·前后端分离·稻城亚丁景区
一条泥憨鱼30 分钟前
拦截器与过滤器:一次请求穿过 Spring 时,会先经过谁呢
java·开发语言·后端·spring
Shaoshing32 分钟前
二分模板(左右查询)
java·算法·二分
小七在进步32 分钟前
C++内存管理:new/delete vs malloc/free深度解析
android·java·c++