Skip to content

在 Java 中,创建线程的方式主要有以下几种方式。每种方法有不同的用途和实现方式,适用于不同的场景。下面是 Java 中创建线程的常见方法。

1. 继承 Thread

通过继承 Thread 类,重写 run() 方法来定义线程的任务,然后创建该类的实例并调用 start() 方法来启动线程。

示例:

java
class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的任务
        System.out.println("线程运行中...");
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();  // 启动线程
    }
}

说明:

  • 继承 Thread 类的方式简单直接,但如果你已经继承了其他类,那么就无法再继承 Thread 类,这时候就需要使用其他方式。

2. 实现 Runnable 接口

Runnable 是一个函数式接口,定义了 run() 方法。你可以实现 Runnable 接口并将其传递给 Thread 对象的构造器来创建线程。

示例:

java
class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程执行的任务
        System.out.println("线程运行中...");
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();  // 启动线程
    }
}

说明:

  • 使用 Runnable 接口的方式比继承 Thread 更为灵活,因为 Java 支持类的多重实现接口,因此你可以在同一个类中实现多个接口,而不是受限于单继承。
  • Runnable 可以用来将任务与线程的执行分离,更符合面向对象设计原则。

3. 使用 CallableExecutorService

Callable 是一个带有返回值的接口,它类似于 Runnable,但允许任务在执行后返回一个结果或者抛出异常。可以结合 ExecutorService 来管理线程池,提交任务并获取结果。

示例:

java
import java.util.concurrent.*;

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        // 线程执行的任务,返回结果
        return "任务执行完成";
    }
}

public class CallableExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(1);  // 创建线程池
        MyCallable myCallable = new MyCallable();
        Future<String> future = executor.submit(myCallable);  // 提交任务
        System.out.println(future.get());  // 获取返回结果
        executor.shutdown();  // 关闭线程池
    }
}

说明:

  • Callable 允许任务有返回值,可以捕获执行过程中的异常。
  • ExecutorService 提供了更强大的线程管理功能,可以创建线程池并控制并发的线程数。

4. 使用 ExecutorService 提交 RunnableCallable 任务

ExecutorService 提供了更高层次的抽象,能够管理线程池并执行 RunnableCallable 任务。

示例(使用 ExecutorService 提交 Runnable):

java
import java.util.concurrent.*;

public class ExecutorServiceRunnableExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);  // 创建线程池
        executor.submit(() -> {
            // 执行任务
            System.out.println("线程执行任务...");
        });
        executor.shutdown();  // 关闭线程池
    }
}

示例(使用 ExecutorService 提交 Callable):

java
import java.util.concurrent.*;

public class ExecutorServiceCallableExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(1);  // 创建线程池
        Callable<String> task = () -> {
            // 执行任务,返回结果
            return "任务完成";
        };
        Future<String> future = executor.submit(task);  // 提交任务
        System.out.println(future.get());  // 获取返回结果
        executor.shutdown();  // 关闭线程池
    }
}

说明:

  • ExecutorService 通过线程池管理线程,能够实现更好的资源管理和性能优化。适用于高并发的场景,能够有效管理线程生命周期,避免创建和销毁线程的开销。
  • 提交任务后,你可以使用 Future 对象来跟踪任务的执行结果或异常。

5. 使用 ForkJoinPool

ForkJoinPool 是一种专门设计用于支持大规模并行任务的线程池。它支持 分治算法,将任务拆分成多个子任务,并行执行,最终合并结果。适用于 CPU 密集型的任务。

示例:

java
import java.util.concurrent.*;

public class ForkJoinPoolExample {
    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();  // 创建 ForkJoinPool
        forkJoinPool.submit(() -> {
            // 执行任务
            System.out.println("ForkJoinPool 执行任务...");
        });
        forkJoinPool.shutdown();  // 关闭线程池
    }
}

说明:

  • ForkJoinPool 适用于并行任务的处理,能够自动将任务分解并行处理。它内部使用工作窃取算法,具有高效的线程管理和任务调度能力。
  • 适用于任务拆分和合并的场景,比如计算 Fibonacci 数列、矩阵乘法等。

6. 使用 Lambda 表达式创建线程

Java 8 引入了 Lambda 表达式,可以让代码更简洁。当使用 RunnableCallable 时,可以使用 Lambda 来传递任务。

示例:

java
public class LambdaThreadExample {
    public static void main(String[] args) {
        // 使用 Lambda 表达式创建并启动线程
        Thread thread = new Thread(() -> {
            System.out.println("使用 Lambda 表达式执行任务");
        });
        thread.start();
    }
}

说明:

  • 使用 Lambda 表达式可以使线程创建代码更加简洁。
  • 适合短小的任务,避免了创建单独类或实现接口的冗余代码。

7. 使用 ScheduledExecutorService 定时任务

ScheduledExecutorServiceExecutorService 的一个子接口,提供了任务调度功能,可以用来执行定时或周期性任务。

示例:

java
import java.util.concurrent.*;

public class ScheduledExecutorServiceExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);  // 创建线程池
        scheduler.scheduleAtFixedRate(() -> {
            // 执行定时任务
            System.out.println("定时任务执行...");
        }, 0, 2, TimeUnit.SECONDS);  // 延迟 0 秒后每 2 秒执行一次
    }
}

说明:

  • ScheduledExecutorService 适用于定时任务或周期性任务的调度,可以非常方便地设置任务的延迟和执行间隔。

总结

Java 提供了多种方式来创建线程,不同的方式适用于不同的场景:

方法适用场景
继承 Thread简单任务,不需要控制线程资源的场景。
实现 Runnable 接口多任务执行,任务逻辑与线程分离,线程复用。
使用 CallableExecutorService需要获取任务结果或处理任务异常的场景,适合高并发任务。
使用 ForkJoinPool适合并行处理任务,尤其是大规模的 CPU 密集型任务。
使用 ScheduledExecutorService定时任务和周期性任务。
使用 Lambda 表达式简洁的线程创建方式,适合简单的任务。

✨ 网站运行时间: 3年11月15天 ❤️ 道阻且长,行则将至 - 微信号: heikedreamer