【Java 中创建线程池的方式】

打印 上一主题 下一主题

主题 913|帖子 913|积分 2739

以下是一些常见线程池的创建方式:
1. 使用ThreadPoolExecutor自定义创建线程池

这是企业中最推荐的做法,由于它提供了最大的机动性。
特性与特点:允许准确控制线程池的核心参数,如核心线程数、最大线程数、任务队列容量、线程空闲时间以及饱和计谋等。
  1. import java.util.concurrent.*;
  2. public class CustomThreadPool {
  3.     public static void main(String[] args) {
  4.         // 自定义线程池配置
  5.         int corePoolSize = 5; // 核心线程数
  6.         int maximumPoolSize = 10; // 最大线程数
  7.         long keepAliveTime = 60L; // 空闲线程存活时间
  8.         TimeUnit unit = TimeUnit.SECONDS; // 时间单位
  9.         BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(20); // 任务队列
  10.         ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂
  11.         RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略
  12.         
  13.         ExecutorService executor = new ThreadPoolExecutor(
  14.                 corePoolSize,
  15.                 maximumPoolSize,
  16.                 keepAliveTime,
  17.                 unit,
  18.                 workQueue,
  19.                 threadFactory,
  20.                 handler
  21.         );
  22.         
  23.         // 提交任务到线程池
  24.         for (int i = 0; i < 15; i++) {
  25.             executor.submit(() -> {
  26.                 System.out.println("Task executed by " + Thread.currentThread().getName());
  27.             });
  28.         }
  29.         
  30.         // 关闭线程池
  31.         executor.shutdown();
  32.     }
  33. }
复制代码
核心参数:


  • corePoolSize:核心线程数。
  • maximumPoolSize:最大线程数。
  • keepAliveTime:空闲线程存活时间。
  • workQueue:任务队列,用于存储等待实行的任务。
  • threadFactory:线程工厂,用于创建新线程。
  • handler:拒绝计谋,当线程池无法处置处罚新任务时接纳的计谋。
实行任务流程


  • execute(Runnable command):这是提交任务到线程池的主要方法。
实在行流程大致如下:

  • 直接实行:假如当前运行的线程少于核心线程数,纵然其他线程是空闲的,也会尝试直接创建一个新的线程来实行任务。
  • 参加队列:假如当前线程数等于核心线程数,任务将被放入工作队列中排队。
  • 扩容线程池:假如工作队列已满,且当前线程数小于最大线程数,会创建新的线程来处置处罚任务。
  • 拒绝计谋:假如当前线程数已经到达最大值,且工作队列也满了,就会触发拒绝计谋,通常是抛出非常或忽略该任务。
2. 使用Executors工厂方法

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

形貌: 创建一个固定大小的线程池,该线程池可重用固定数目的线程。假如所有线程都在活动状态,新提交的任务将在队列中等待,直到有线程可用。
特点:线程池大小固定,所有线程都会一直存在直到程序结束,适合于实行大量相似任务的场景。
使用场景:适用于负载较稳固的场景,尤其是当任务数和线程处置处罚能力相对均衡时。
  1. public static ExecutorService newFixedThreadPool(int nThreads) {
  2.     return new ThreadPoolExecutor(nThreads, nThreads,
  3.                                 0L, TimeUnit.MILLISECONDS,
  4.                                 new LinkedBlockingQueue<Runnable>());
  5. }
复制代码
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. public class FixedThreadPoolExample {
  4.     public static void main(String[] args) {
  5.         // 创建一个固定大小为5的线程池
  6.         ExecutorService executor = Executors.newFixedThreadPool(5);
  7.         
  8.         for (int i = 0; i < 10; i++) {
  9.             final int taskId = i;
  10.             executor.execute(() -> {
  11.                 System.out.println("Task ID " + taskId + " is running in " + Thread.currentThread().getName());
  12.             });
  13.         }
  14.         
  15.         // 关闭线程池(最好在应用程序结束时执行)
  16.         executor.shutdown();
  17.         while (!executor.isTerminated()) {
  18.             // 等待所有任务完成
  19.         }
  20.         System.out.println("Finished all threads");
  21.     }
  22. }
复制代码
2.2. CachedThreadPool(可缓存线程池)

形貌: 创建一个可根据必要创建新线程的线程池,线程池在必要时创建新线程,假如现有线程空闲超过60秒,则会被回收。
特点:线程池会根据必要创建新线程,假如有空闲线程则重用,否则新建。空闲线程在默认情况下存活60秒后被停止。
使用场景:适用于实行很多短期异步任务,如处置处罚HTTP哀求、实行短小的背景任务。
  1. public static ExecutorService newCachedThreadPool() {
  2.     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
  3.                                 60L, TimeUnit.SECONDS,
  4.                                 new SynchronousQueue<Runnable>());
  5. }
复制代码
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. public class CachedThreadPoolExample {
  4.     public static void main(String[] args) {
  5.         ExecutorService executor = Executors.newCachedThreadPool();
  6.         
  7.         for (int i = 0; i < 10; i++) {
  8.             final int taskId = i;
  9.             executor.execute(() -> {
  10.                 System.out.println("Task ID " + taskId + " is running in " + Thread.currentThread().getName());
  11.             });
  12.         }
  13.         
  14.         executor.shutdown();
  15.     }
  16. }
复制代码
2.3. SingleThreadExecutor(单线程线程池)

形貌: 创建一个只有一个线程的线程池,所有任务按照提交顺序依次实行。
特点:该线程池只使用一个线程来实行任务,任务按照提交顺序实行,适用于不必要并发但必要顺序处置处罚的场景。
使用场景:适用于必要保证顺序实行任务的场景,或作为背景任务处置处罚器。
  1. public static ExecutorService newSingleThreadExecutor() {
  2.     return new FinalizableDelegatedExecutorService
  3.         (new ThreadPoolExecutor(1, 1,
  4.                                0L, TimeUnit.MILLISECONDS,
  5.                                new LinkedBlockingQueue<Runnable>()));
  6. }
复制代码
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. public class SingleThreadExecutorExample {
  4.     public static void main(String[] args) {
  5.         ExecutorService executor = Executors.newSingleThreadExecutor();
  6.         
  7.         for (int i = 0; i < 10; i++) {
  8.             final int taskId = i;
  9.             executor.execute(() -> {
  10.                 System.out.println("Task ID " + taskId + " is running in " + Thread.currentThread().getName());
  11.             });
  12.         }
  13.         
  14.         executor.shutdown();
  15.     }
  16. }
复制代码
2.4. ScheduledThreadPool(定时/周期性任务线程池)

形貌: 创建一个支持定时及周期性实行任务的线程池。核心线程数固定,别的线程在无任务时会被回收。
特点:可以安排任务在未来的某个时间点实行,或者定期重复实行。适用于定时任务和周期性任务。
使用场景:实行定时任务,如定时数据同步、定时清理、定时查抄等。
  1. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
  2.     return new ScheduledThreadPoolExecutor(corePoolSize);
  3. }
复制代码
  1. import java.util.concurrent.Executors;
  2. import java.util.concurrent.ScheduledExecutorService;
  3. import java.util.concurrent.TimeUnit;
  4. public class ScheduledThreadPoolExample {
  5.     public static void main(String[] args) {
  6.         ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
  7.         
  8.         Runnable task = () -> System.out.println("Task executed at " + System.currentTimeMillis());
  9.         
  10.         // 延迟5秒后执行一次
  11.         executor.schedule(task, 5, TimeUnit.SECONDS);
  12.         
  13.         // 每隔3秒执行一次
  14.         executor.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
  15.         
  16.         // 在关闭前,通常应有逻辑来决定何时停止调度
  17.         // 这里为了简化,直接关闭线程池,但在实际应用中应避免立即关闭以免任务未完成
  18.         executor.shutdown();
  19.         while (!executor.isTerminated()) {}
  20.         System.out.println("Finished all scheduled tasks");
  21.     }
  22. }
复制代码
底层实现
上述所有Executors工厂方法创建线程池的实现终极都基于ThreadPoolExecutor类,它内部维护了工作线程聚集、任务队列、同步控制锁等,以确保任务能够高效、安全地分配给线程实行,并处置处罚线程的生命周期管理、任务调理和拒绝计谋等题目。自定义配置线程池时,通过调解ThreadPoolExecutor的构造参数,可以针对特定应用场景优化性能和资源利用率。
特性总结


  • 机动性: Executors提供的工厂方法简化了线程池的创建,使得开发者无需直接与ThreadPoolExecutor复杂的构造参数打交道。
  • 易用性: 提供了多种预设的线程池模子,满意不同场景下的需求。
  • 潜在风险: 只管方便,但直接使用这些方法可能会导致资源管理不当(如无限增长的队列、过多线程),因此现代实践中更推荐直接使用ThreadPoolExecutor举行定制化配置,以更好地控制和理解线程池的行为。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连密封材料

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表