1. 继承Thread
类
原理
Thread
类是Java中用于实现线程的类,通过继承Thread
类,并重写其run()
方法来定义线程要执行的任务。
示例代码
// 继承Thread类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
}
}
public class ThreadInheritanceExample {
public static void main(String[] args) {
// 创建线程对象
MyThread myThread = new MyThread();
// 启动线程
myThread.start();
}
}
优缺点
- 优点:实现简单,对于初学者容易理解。
- 缺点:由于Java是单继承的,继承了
Thread
类后就不能再继承其他类,会限制代码的可扩展性。
2. 实现Runnable
接口
原理
Runnable
接口中只有一个抽象方法run()
,通过实现该接口并将实现类的实例作为参数传递给Thread
类的构造函数来创建线程。
示例代码
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
}
}
public class RunnableImplementationExample {
public static void main(String[] args) {
// 创建实现Runnable接口的类的实例
MyRunnable myRunnable = new MyRunnable();
// 创建线程对象,将Runnable实例作为参数传递
Thread thread = new Thread(myRunnable);
// 启动线程
thread.start();
}
}
优缺点
- 优点:避免了单继承的限制,一个类可以在实现
Runnable
接口的同时继承其他类,代码更具灵活性和可维护性。 - 缺点:代码稍微复杂一些,需要创建
Runnable
实现类的实例并传递给Thread
类。
3. 实现Callable
接口并结合FutureTask
原理
Callable
接口中的call()
方法可以有返回值,并且可以抛出异常。通过FutureTask
类将Callable
实例包装起来,再将FutureTask
实例传递给Thread
类来创建线程。
示例代码
import java.util.concurrent.*;
// 实现Callable接口
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
return 100;
}
}
public class CallableExample {
public static void main(String[] args) {
// 创建Callable实例
MyCallable myCallable = new MyCallable();
// 创建FutureTask实例,将Callable实例作为参数传递
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
// 创建线程对象,将FutureTask实例作为参数传递
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();
try {
// 获取线程执行结果
Integer result = futureTask.get();
System.out.println("线程执行结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
优缺点
- 优点:可以获取线程执行的返回结果,适用于需要获取线程执行结果的场景。
- 缺点:代码复杂度较高,涉及到
Callable
、FutureTask
等类的使用。
4. 使用线程池
原理
线程池可以管理和复用线程,避免了频繁创建和销毁线程带来的性能开销。通过Executors
工具类或ThreadPoolExecutor
类来创建线程池,将任务提交给线程池执行。
示例代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// 实现Runnable接口
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
}
}
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 提交任务给线程池执行
for (int i = 0; i < 5; i++) {
executorService.submit(new MyTask());
}
// 关闭线程池
executorService.shutdown();
}
}
优缺点
- 优点:提高了线程的复用性和系统的性能,减少了线程创建和销毁的开销,同时可以更好地管理线程资源。
- 缺点:使用相对复杂,需要了解线程池的各种参数和配置。
综上所述,在实际开发中,推荐使用实现Runnable
接口或使用线程池的方式来创建线程,因为它们更具灵活性和性能优势。