实现一个简单的线程池

2025-3-10 diaba

实现一个简单的线程池需要考虑以下几个关键点:

  1. 任务队列:用于存储待执行的任务。
  2. 工作线程:线程池中的线程,负责从任务队列中取出任务并执行。
  3. 任务提交:提供方法允许外部提交任务到线程池。
  4. 线程管理:控制线程的创建、销毁和复用。

以下是一个简单的线程池实现,支持任务的提交和执行:

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class SimpleThreadPool {
    // 线程池中的线程数量
    private final int poolSize;
    // 任务队列
    private final Queue<Runnable> taskQueue = new LinkedList<>();
    // 线程池中的工作线程
    private final WorkerThread[] threads;
    // 锁和条件变量
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition();
    // 线程池是否关闭
    private volatile boolean isShutdown = false;

    public SimpleThreadPool(int poolSize) {
        this.poolSize = poolSize;
        this.threads = new WorkerThread[poolSize];

        // 创建并启动工作线程
        for (int i = 0; i < poolSize; i++) {
            threads[i] = new WorkerThread();
            threads[i].start();
        }
    }

    // 提交任务到线程池
    public void submit(Runnable task) {
        if (isShutdown) {
            throw new IllegalStateException("Thread pool is shut down.");
        }

        lock.lock();
        try {
            taskQueue.add(task);
            notEmpty.signal(); // 唤醒一个等待的工作线程
        } finally {
            lock.unlock();
        }
    }

    // 关闭线程池
    public void shutdown() {
        lock.lock();
        try {
            isShutdown = true;
            notEmpty.signalAll(); // 唤醒所有等待的工作线程
        } finally {
            lock.unlock();
        }
    }

    // 工作线程类
    private class WorkerThread extends Thread {
        @Override
        public void run() {
            while (true) {
                Runnable task = null;

                lock.lock();
                try {
                    // 检查线程池是否关闭
                    if (isShutdown && taskQueue.isEmpty()) {
                        return; // 如果线程池关闭且任务队列为空,则退出线程
                    }

                    // 如果任务队列为空,则等待
                    while (taskQueue.isEmpty() && !isShutdown) {
                        notEmpty.await();
                    }

                    // 如果线程池未关闭,则取出一个任务
                    if (!isShutdown) {
                        task = taskQueue.poll();
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }

                // 执行任务
                if (task != null) {
                    task.run();
                }
            }
        }
    }
}

代码解析

  1. 任务队列

    • 使用LinkedList作为任务队列,存储待执行的任务。
    • 使用ReentrantLockCondition来实现线程安全的任务队列操作。
  2. 工作线程

    • 每个工作线程继承自Thread类,重写run方法。
    • 工作线程在运行时会不断从任务队列中取出任务并执行。
    • 如果任务队列为空,工作线程会调用notEmpty.await()进入等待状态,直到有任务被提交。
  3. 任务提交

    • 提供submit方法,允许外部提交任务到线程池。
    • 提交任务时,将任务添加到任务队列,并调用notEmpty.signal()唤醒一个等待的工作线程。
  4. 线程池关闭

    • 提供shutdown方法,关闭线程池。
    • 设置isShutdown标志为true,并调用notEmpty.signalAll()唤醒所有等待的工作线程。
    • 工作线程在检测到isShutdowntrue且任务队列为空时,退出运行。

使用示例

public class Main {
    public static void main(String[] args) {
        SimpleThreadPool threadPool = new SimpleThreadPool(4); // 创建一个包含4个工作线程的线程池

        // 提交任务
        for (int i = 0; i < 10; i++) {
            int taskNumber = i;
            threadPool.submit(() -> {
                System.out.println("Executing task: " + taskNumber + " on thread: " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000); // 模拟任务执行时间
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 关闭线程池
        threadPool.shutdown();
    }
}

输出示例

Executing task: 0 on thread: WorkerThread-0
Executing task: 1 on thread: WorkerThread-1
Executing task: 2 on thread: WorkerThread-2
Executing task: 3 on thread: WorkerThread-3
Executing task: 4 on thread: WorkerThread-0
Executing task: 5 on thread: WorkerThread-1
Executing task: 6 on thread: WorkerThread-2
Executing task: 7 on thread: WorkerThread-3
Executing task: 8 on thread: WorkerThread-0
Executing task: 9 on thread: WorkerThread-1 

注意事项

  1. 线程安全:使用ReentrantLockCondition确保任务队列操作的线程安全。
  2. 优雅关闭:在关闭线程池时,确保所有任务都被执行完毕,然后让工作线程安全退出。
  3. 异常处理:在实际应用中,需要对任务执行中的异常进行处理,避免一个任务的失败导致整个线程池停止工作。

这个简单的线程池实现可以作为学习和理解线程池工作原理的基础。在实际项目中,建议使用Java标准库中的java.util.concurrent包提供的线程池实现(如ExecutorService),它们经过了严格的测试和优化,功能更加完善。

发表评论:

Powered by emlog 京ICP备15045175号-1 Copyright © 2022