线程池的使用流程

发布于:2025-02-12 ⋅ 阅读:(135) ⋅ 点赞:(0)

线程池(Thread Pool)是一种管理和复用线程的机制,能够有效减少线程创建和销毁的开销,提高系统性能。以下是线程池的使用流程,以Java中的`ThreadPoolExecutor`为例:

 

---

 

### 1. **创建线程池**

Java提供了`Executors`工具类来快速创建线程池,也可以直接使用`ThreadPoolExecutor`构造函数自定义线程池。

 

#### 1.1 使用`Executors`创建线程池

```java

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

 

// 创建固定大小的线程池

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

 

// 创建缓存线程池(根据需要创建新线程)

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

 

// 创建单线程线程池

ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

 

// 创建定时任务线程池

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

```

 

#### 1.2 使用`ThreadPoolExecutor`自定义线程池

```java

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.LinkedBlockingQueue;

 

int corePoolSize = 5; // 核心线程数

int maxPoolSize = 10; // 最大线程数

long keepAliveTime = 60; // 空闲线程存活时间

TimeUnit unit = TimeUnit.SECONDS; // 时间单位

LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100); // 任务队列

 

ThreadPoolExecutor executor = new ThreadPoolExecutor(

    corePoolSize,

    maxPoolSize,

    keepAliveTime,

    unit,

    workQueue

);

```

 

---

 

### 2. **提交任务**

将任务提交到线程池中执行。任务可以是`Runnable`或`Callable`。

 

#### 2.1 提交`Runnable`任务

```java

executor.execute(() -> {

    System.out.println("Task executed by " + Thread.currentThread().getName());

});

```

 

#### 2.2 提交`Callable`任务

```java

import java.util.concurrent.Future;

 

Future<String> future = executor.submit(() -> {

    return "Task result";

});

 

// 获取任务执行结果

String result = future.get();

System.out.println("Task result: " + result);

```

 

---

 

### 3. **关闭线程池**

当线程池不再需要时,应正确关闭以释放资源。

 

#### 3.1 正常关闭

```java

executor.shutdown(); // 停止接收新任务,等待已提交任务执行完成

```

 

#### 3.2 立即关闭

```java

executor.shutdownNow(); // 尝试停止所有正在执行的任务,并返回等待执行的任务列表

```

 

#### 3.3 等待线程池终止

```java

if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {

    executor.shutdownNow(); // 强制关闭

}

```

 

---

 

### 4. **线程池参数配置**

线程池的核心参数包括:

- **核心线程数(corePoolSize)**:线程池中始终保持存活的线程数。

- **最大线程数(maxPoolSize)**:线程池中允许的最大线程数。

- **空闲线程存活时间(keepAliveTime)**:当线程数超过核心线程数时,空闲线程的存活时间。

- **任务队列(workQueue)**:用于存放等待执行的任务。

- **线程工厂(threadFactory)**:用于创建新线程。

- **拒绝策略(rejectedExecutionHandler)**:当任务队列已满且线程数达到最大值时的处理策略。

 

---

 

### 5. **拒绝策略**

当任务队列已满且线程数达到最大值时,线程池会触发拒绝策略。Java提供了以下内置策略:

- **AbortPolicy**:默认策略,直接抛出`RejectedExecutionException`。

- **CallerRunsPolicy**:由提交任务的线程直接执行任务。

- **DiscardPolicy**:直接丢弃任务,不抛出异常。

- **DiscardOldestPolicy**:丢弃队列中最旧的任务,然后重新提交当前任务。

 

```java

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

```

 

---

 

### 6. **监控线程池状态**

可以通过以下方法监控线程池的状态:

- **`getPoolSize()`**:获取当前线程池中的线程数。

- **`getActiveCount()`**:获取正在执行任务的线程数。

- **`getCompletedTaskCount()`**:获取已完成的任务数。

- **`getQueue().size()`**:获取任务队列中的任务数。

 

```java

System.out.println("Pool Size: " + executor.getPoolSize());

System.out.println("Active Threads: " + executor.getActiveCount());

System.out.println("Completed Tasks: " + executor.getCompletedTaskCount());

System.out.println("Queue Size: " + executor.getQueue().size());

```

 

---

 

### 7. **线程池的使用场景**

- **CPU密集型任务**:核心线程数设置为CPU核心数 + 1。

- **IO密集型任务**:核心线程数可以设置得更大一些,以充分利用CPU资源。

- **定时任务**:使用`ScheduledThreadPoolExecutor`。

 

---

 

### 8. **注意事项**

- **避免任务队列过大**:任务队列过大会导致内存占用过高,甚至OOM。

- **合理设置线程数**:根据任务类型(CPU密集型或IO密集型)设置合适的线程数。

- **及时关闭线程池**:避免资源泄漏。

 

---

 

### 示例代码

```java

import java.util.concurrent.*;

 

public class ThreadPoolExample {

    public static void main(String[] args) {

        // 创建线程池

        ThreadPoolExecutor executor = new ThreadPoolExecutor(

            2, // 核心线程数

            4, // 最大线程数

            60, // 空闲线程存活时间

            TimeUnit.SECONDS, // 时间单位

            new LinkedBlockingQueue<>(10) // 任务队列

        );

 

        // 提交任务

        for (int i = 0; i < 10; i++) {

            executor.execute(() -> {

                System.out.println("Task executed by " + Thread.currentThread().getName());

            });

        }

 

        // 关闭线程池

        executor.shutdown();

    }

}

```

 

---

 

通过以上流程,可以高效地使用线程池来管理多线程任务,提升系统性能。


网站公告

今日签到

点亮在社区的每一天
去签到