创建线程的方式有几种
1. 继承 Thread 类
这是最直接的一种方式,通过创建一个继承自 Thread 类的子类,并重写其 run() 方法来定义线程需要执行的任务。
实现步骤:
- 定义一个类继承
Thread类。 - 重写
run()方法,将线程要执行的逻辑代码放入其中。 - 创建该子类的实例,即创建了线程对象。
- 调用线程对象的
start()方法来启动线程。
示例:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("通过继承Thread类创建线程...");
}
}
// 启动线程
MyThread t = new MyThread();
t.start();
2. 实现 Runnable 接口
这种方式下,线程的执行任务(Runnable)与线程的创建和管理(Thread)是分离的。
实现步骤:
- 定义一个类实现
Runnable接口。 - 实现
run()方法,这个方法是线程的执行体。 - 创建
Runnable实现类的实例。 - 将该实例作为参数传递给
Thread类的构造函数来创建线程对象。 - 调用
Thread对象的start()方法。
示例:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("通过实现Runnable接口创建线程...");
}
}
// 启动线程
MyRunnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable);
t.start();
3. 实现 Callable 接口(配合 FutureTask 或线程池)
从 Java 1.5 开始引入,这种方式是对 Runnable 的一个重要补充,主要用于需要获取线程执行结果或处理线程抛出异常的场景。
实现步骤:
- 创建一个类实现
Callable<V>接口,其中V是返回值的类型。 - 实现
call()方法,该方法有返回值,并且可以抛出异常。 - 使用
FutureTask类来包装Callable对象。 - 将
FutureTask对象作为参数传递给Thread构造函数并启动线程。 - 通过
FutureTask对象的get()方法获取线程执行的返回值(该方法会阻塞,直到任务完成)。
示例:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(1000);
return "线程执行完成";
}
}
// 启动线程并获取结果
MyCallable myCallable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(myCallable);
Thread t = new Thread(futureTask);
t.start();
// 获取返回值
String result = futureTask.get(); // 阻塞等待
System.out.println(result);
4. 使用线程池
在实际开发中,频繁地创建和销毁线程会带来很大的性能开销。因此,更推荐使用线程池来管理线程。线程池可以复用已创建的线程,控制并发线程的数量。
实现步骤:
- 使用
Executors工厂类创建所需类型的线程池(如newFixedThreadPool,newCachedThreadPool等)。 - 创建实现了
Runnable或Callable接口的任务。 - 通过线程池的
submit()或execute()方法提交任务。 - 当不再需要线程池时,调用
shutdown()方法关闭。
示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// ... MyRunnable class from above ...
// 创建线程池并提交任务
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.execute(new MyRunnable());
executorService.shutdown();