在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类创建多个线程时,每个线程都是独立的对象,若要实现资源共享,需额外的操作。