Skip to content

在 Java 中,线程池是用来管理线程的一种机制,它能帮助你控制并发执行的任务,并复用线程以避免频繁地创建和销毁线程。Java 提供了多种线程池实现,可以根据不同的需求选择合适的线程池。

1. FixedThreadPool(固定大小线程池)

FixedThreadPool 是一个固定大小的线程池,线程池中的线程数是固定的。如果有多个任务提交,线程池会重用现有的线程来执行任务,直到任务数量超过线程池中的线程数。

特点:

  • 固定大小的线程池。
  • 如果线程池中有空闲线程,就会复用这些线程。
  • 当线程数达到最大值时,其他任务会被放入队列中等待执行。

示例:

java
import java.util.concurrent.*;

public class FixedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(4); // 创建一个固定大小的线程池
        
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("执行任务:" + taskId);
                try {
                    Thread.sleep(2000);  // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        executorService.shutdown(); // 关闭线程池
    }
}

2. CachedThreadPool(可缓存线程池)

CachedThreadPool 是一个可根据需求创建新线程的线程池。如果有空闲线程,则会复用线程;如果没有空闲线程且当前没有线程处理任务,则会创建一个新线程。

特点:

  • 动态创建线程,数量不固定。
  • 对于长期闲置的线程,线程池会在一定时间后自动回收。
  • 适合处理大量短期任务的场景。

示例:

java
import java.util.concurrent.*;

public class CachedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool(); // 创建一个可缓存的线程池
        
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("执行任务:" + taskId);
                try {
                    Thread.sleep(2000);  // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        executorService.shutdown(); // 关闭线程池
    }
}

3. SingleThreadExecutor(单线程线程池)

SingleThreadExecutor 是一个单线程的线程池,它只有一个工作线程来执行任务。如果有多个任务提交,任务会按照提交的顺序排队执行,任务之间是顺序执行的。

特点:

  • 只使用一个线程执行任务,适合串行化执行的场景。
  • 任务按照提交的顺序执行,保证任务执行顺序。
  • 如果当前线程发生异常或被中断,线程池会创建一个新的线程继续执行任务。

示例:

java
import java.util.concurrent.*;

public class SingleThreadExecutorExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor(); // 创建一个单线程线程池
        
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("执行任务:" + taskId);
                try {
                    Thread.sleep(2000);  // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        executorService.shutdown(); // 关闭线程池
    }
}

4. ScheduledThreadPoolExecutor(定时任务线程池)

ScheduledThreadPoolExecutor 用于执行定时任务。它可以周期性地执行任务,也可以在延迟一段时间后执行任务。

特点:

  • 支持延迟任务和定期任务。
  • 适用于需要定时执行任务的场景(例如,周期性的日志记录、定时清理任务等)。

示例:

java
import java.util.concurrent.*;

public class ScheduledThreadPoolExecutorExample {
    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); // 创建一个定时任务线程池
        
        // 延迟 3 秒后执行任务
        executorService.schedule(() -> {
            System.out.println("延迟 3 秒执行的任务");
        }, 3, TimeUnit.SECONDS);
        
        // 每 2 秒执行一次任务
        executorService.scheduleAtFixedRate(() -> {
            System.out.println("定时执行的任务");
        }, 0, 2, TimeUnit.SECONDS);
        
        // 每 2 秒执行一次任务,执行完成后再等待 2 秒
        executorService.scheduleWithFixedDelay(() -> {
            System.out.println("定时执行并延迟的任务");
        }, 0, 2, TimeUnit.SECONDS);
    }
}

5. WorkStealingPool(工作窃取线程池)

WorkStealingPool 是一个新的线程池实现,在 Java 8 中引入。它适用于具有多任务并行执行的场景,通过“工作窃取”机制将任务分配给空闲线程,从而提高并行度。

特点:

  • 采用“工作窃取”算法,空闲的线程会窃取有任务的线程的任务。
  • 适用于处理 CPU 密集型任务或者具有大量短任务的场景。

示例:

java
import java.util.concurrent.*;

public class WorkStealingPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newWorkStealingPool(); // 创建一个工作窃取线程池
        
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("执行任务:" + taskId);
                try {
                    Thread.sleep(2000);  // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        executorService.shutdown(); // 关闭线程池
    }
}

6. Custom ThreadPool (自定义线程池)

除了使用 Executors 工厂方法创建线程池外,你也可以通过 ThreadPoolExecutor 类来自定义线程池的行为。你可以指定线程池的核心线程数、最大线程数、空闲线程存活时间等参数。

示例:

java
import java.util.concurrent.*;

public class CustomThreadPoolExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(
                2, // 核心线程数
                4, // 最大线程数
                60, // 空闲线程存活时间
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10)); // 阻塞队列,最大容量为 10
        
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("执行任务:" + taskId);
                try {
                    Thread.sleep(2000);  // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        executorService.shutdown(); // 关闭线程池
    }
}

总结:

  • FixedThreadPool:固定大小的线程池,适合处理任务量已知且相对稳定的场景。
  • CachedThreadPool:动态调整线程池大小,适合处理大量短任务。
  • SingleThreadExecutor:单线程执行任务,适合串行化任务。
  • ScheduledThreadPoolExecutor:定时任务线程池,适合周期性或延迟执行的任务。
  • WorkStealingPool:适合 CPU 密集型任务,采用工作窃取算法提高效率。
  • Custom ThreadPool (ThreadPoolExecutor):自定义线程池,可以根据需求定制线程池的行为和参数。

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