Skip to content

面试速答(先看这里)

**一句话结论:**其实,归根结底最终就两种,一个是继承 Thread 类,一个是实现 Runnable 接口,至于其他的。

60秒标准回答:

在Java中,共有四种方式可以创建线程,分别是

其实,归根结底最终就两种,一个是继承 Thread 类,一个是实现 Runnable 接口,至于其他的。也是基于这两个方式实现的。但是有的时候面试官更关注的是实际写代码过程中,有几种方式可以实现。所以一般回答4种也没啥毛病

Runnable接口和Callable接口都可以用来创建新线程,实现Runnable的时候,需要实现run方法;实现Callable接口的话,需要实现call方法

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**在Java中,共有四种方式可以创建线程,分别是
  • **要点2:**Runnable接口和Callable接口都可以用来创建新线程,实现Runnable的时候,需要实现run方法;
  • **要点3:**Runnable的run方法无返回值,Callable的call方法有返回值,类型为Object
  • **要点4:**Callable中可以够抛出checked exception,而Runnable不可以。
  • **要点5:**FutureTask是Future接口的一个实现,它实现了一个可以提交给Executor执行的任务,并且可以用来检查任务的执行状态和获取任务的执行结果。

**记忆锚点:**Runnable → Callable → Thread → FutureTask → Future → 创建线程

加分表达:

  • 如果想取消,那么调用cancel()方法。

追问准备:

  • 围绕「Runnable」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「Callable」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「Thread」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

在Java中,共有四种方式可以创建线程,分别是

  • 继承Thread类创建线程
  • 实现Runnable接口创建线程
  • 通过Callable和FutureTask创建线程
  • 通过线程池创建线程

> 其实,归根结底最终就两种,一个是继承Thread类,一个是实现Runnable接口,至于其他的。也是基于这两个方式实现的。但是有的时候面试官更关注的是实际写代码过程中,有几种方式可以实现。所以一般回答4种也没啥毛病。

扩展知识 ​

Runnable和Callable区别 ​

Runnable接口和Callable接口都可以用来创建新线程,实现Runnable的时候,需要实现run方法;实现Callable接口的话,需要实现call方法。

Runnable的run方法无返回值,Callable的call方法有返回值,类型为Object

Callable中可以够抛出checked exception,而Runnable不可以。

Callable和Runnable都可以应用于executors。而Thread类只支持Runnable。

Future ​

Future是一个接口,代表了一个异步执行的结果。接口中的方法用来检查执行是否完成、等待完成和得到执行的结果。当执行完成后,只能通过get()方法得到结果,get方法会阻塞直到结果准备好了。如果想取消,那么调用cancel()方法。

FutureTask是Future接口的一个实现,它实现了一个可以提交给Executor执行的任务,并且可以用来检查任务的执行状态和获取任务的执行结果。

FutureTask和Callable示例 ​

java
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureAndCallableExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Callable<String> callable = () -> {
            System.out.println("Entered Callable");
            Thread.sleep(2000);
            return "Hello from Callable";
        };

        FutureTask<String> futureTask = new FutureTask<>(callable);
        Thread thread = new Thread(futureTask);
        thread.start();

        System.out.println("Do something else while callable is getting executed");
        System.out.println("Retrieved: " + futureTask.get());
    }
}

线程池 ​

📄 ✅什么是线程池,如何实现的?

打开文档:✅什么是线程池,如何实现的?

线程池和Callable的示例 ​

java
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureAndCallableExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Callable<String> callable = () -> {
            System.out.println("Entered Callable");
            Thread.sleep(2000);
            return "Hello from Callable";
        };

        System.out.println("Submitting Callable");
        Future<String> future = executor.submit(callable);

        System.out.println("Do something else while callable is getting executed");
        System.out.println("Retrieved: " + future.get());

        executor.shutdown();
    }
}