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