在Java里,线程创建主要有以下三种方式:

1. 继承 Thread

通过创建一个继承自 Thread 类的子类,并重写其 run() 方法,在 run() 方法中定义线程要执行的任务。示例代码如下:

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承 Thread 类创建的线程正在执行");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

2. 实现 Runnable 接口

创建一个实现 Runnable 接口的类,实现其 run() 方法,然后将该类的实例作为参数传递给 Thread 类的构造函数来创建线程。示例代码如下:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("实现 Runnable 接口创建的线程正在执行");
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

3. 实现 Callable 接口

创建一个实现 Callable 接口的类,实现其 call() 方法,该方法有返回值。然后使用 FutureTask 类来包装 Callable 对象,再将 FutureTask 对象作为参数传递给 Thread 类的构造函数来创建线程,最后可以通过 FutureTask 对象获取线程执行的结果。示例代码如下:

import java.util.concurrent.*;

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("实现 Callable 接口创建的线程正在执行");
        return 123;
    }
}

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
        Thread thread = new Thread(futureTask);
        thread.start();
        Integer result = futureTask.get();
        System.out.println("线程执行结果: " + result);
    }
}

区别

  • 继承关系与设计灵活性:继承 Thread 类的方式会受到Java单继承特性的限制,若一个类已经继承了其他类,就无法再继承 Thread 类。而实现 Runnable 接口和 Callable 接口则不受此限制,能更好地遵循面向对象的设计原则,提高代码的可维护性和可扩展性。
  • 返回值Thread 类和实现 Runnable 接口的方式,其 run() 方法均无返回值。而实现 Callable 接口的 call() 方法有返回值,还能抛出异常,可通过 FutureTask 获取线程执行结果,适合需要获取线程执行结果的场景。
  • 资源共享:使用 Runnable 接口和 Callable 接口可以让多个线程共享同一个任务对象,方便实现资源共享。而继承 Thread 类创建多个线程时,每个线程都是独立的对象,若要实现资源共享,需额外的操作。