线程实现的三种方式其实是同一种?

从我实习面试开始就有在面试中遇到过这个问题:创建线程有几种方法

记得当时的回答是:在jdk1.5之后有三种创建方式

1.继承Thread类

2.实现Runnable接口

3.实现Callable接口

工作之后回顾这个问题就会想到,这三种方式的不同点在哪呢?所有有了探究的这篇文章

虽然网上已经有很多文章珠玉在前,但是我还是想写一篇我自己的文章,如果写的不好,请见谅

先来实现最基本的创建线程的三种方式吧
1.继承Thread类
/**
 * @author miao
 */
public class ThreadDemo extends Thread {

    private final String threadName;

    public ThreadDemo(String threadName) {
        this.threadName = threadName;
    }

    @Override
    public void run() {

        System.out.println(threadName + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // 多线程级别调用
        new ThreadDemo("test thread demo:").start();

        // 方法级别的调用
         new ThreadDemo("test thread demo:").run();
    }
}
2.实现Runnable接口
/**
 * @author miao
 */
public class RunnableDemo implements Runnable {

    @Override
    public void run() {
        System.out.println("RunnableDemo:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {

        Thread thread = new Thread(new RunnableDemo());

        thread.start();
    }
}
3.实现Callable接口
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * @author miao
 */
public class FutureTaskDemo implements Callable<String> {

    @Override
    public String call() throws Exception {

        return "return callable demo";
    }

    public static void main(String[] args) throws Exception {
        
        FutureTask task = new FutureTask(new FutureTaskDemo());
        new Thread(task).start();
        System.out.println(task.get());
    }
}

已经完成了三种创建线程的方式了,那么我们就来思考一下这三种方式的相同点和不同点吧

其实关于最常见面试题的就是:Runnable与Callable的不同点是什么?

一般同学会回答:Runnable无返回值,而Callable有返回值能抛异常

其实,这三种创建线程的方式本质上是一样的!!!!不信的话看我证明吧

首先是第一种方式,继承Thread类,点开这个类我们可以看到,其实Thread实现了Runnable接口,重写了run()方法

在这里插入图片描述
在这里插入图片描述

第二种方法我们就不说了,因为他本身就是实现的Runnable接口,我们继续来看第三种实现Callable的接口。
首先我们要看的是FutureTask<V>,实现了RunnableFuture<V>接口,再点开RunnableFuture<V>接口看,继承了
Runnable,Future<V>接口,所以说到底还是与Runnable接口有关

在这里插入图片描述

在这里插入图片描述

其实文章到这里就可以结束了,但是我看到第三种Callable方法中能通过get()获取到返回值,那又是在什么时候set进去的呢?

为此我点开了FutureTaskrun()方法查找结果,答案如下,在调用完call()方法后,执行set(result)进去,所以我们后面能通过get()方法获取到result

在这里插入图片描述

结论:线程有三种创建方式,但本质上都是通过实现Runnable接口重写run()方法来的,而Callable的返回值是在成功调用了call()方法后set(result)进去的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值