java中 什么是Executors

在 Java 中,Executors 是一个工具类,它提供了用于创建和管理线程池的一些便捷方法。Executors 类位于 java.util.concurrent 包中,主要用于简化 ThreadPoolExecutor 的创建过程,为开发者提供了几种常用的线程池实现,如固定大小线程池、单线程池、缓存线程池和定时调度线程池等。

1. 什么是 Executors 类?

Executors 类是一个工厂类,它提供了一些静态工厂方法来创建不同类型的线程池。使用 Executors 类可以非常方便地创建和管理线程池,而不需要手动配置 ThreadPoolExecutor 的参数。它可以帮助开发者快速创建适合特定需求的线程池。

Executors 通过以下静态方法来提供线程池的创建:

  • newFixedThreadPool(int nThreads):创建一个固定大小的线程池。
  • newCachedThreadPool():创建一个可以根据需要创建新线程的线程池。
  • newSingleThreadExecutor():创建一个只有一个线程的线程池。
  • newScheduledThreadPool(int corePoolSize):创建一个支持定时和周期性任务执行的线程池。

2. Executors 提供的常用线程池

Executors 提供的几种常用线程池涵盖了不同的应用场景,下面是它们的详细介绍:

2.1 newFixedThreadPool(int nThreads)

newFixedThreadPool(int nThreads) 方法创建一个固定大小的线程池。该线程池中的线程数始终固定,当有任务提交时,如果线程池中的线程都在执行任务,新的任务将会进入等待队列,直到有空闲线程可以执行任务。

  • 特点
      - 线程池的线程数固定,避免了频繁创建和销毁线程的开销。
      - 适用于负载较重的服务器环境,可以通过限制线程数量来保证系统的稳定性。
      - 任务队列采用无界队列(LinkedBlockingQueue),不会拒绝任务。

  • 使用场景:适用于执行长期任务或控制线程数量的场景,如服务器处理请求时限制最大并发线程数。

  • 示例代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FixedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); // 创建一个固定大小为3的线程池

        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            fixedThreadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
                try {
                    Thread.sleep(2000); // 模拟任务执行耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        fixedThreadPool.shutdown(); // 关闭线程池
    }
}
2.2 newCachedThreadPool()

newCachedThreadPool() 方法创建一个可以根据需要创建新线程的线程池。该线程池会根据任务的需要来动态创建线程,线程的数量几乎没有限制(取决于 JVM 和系统资源)。当任务执行完毕后,空闲线程会被缓存,如果线程空闲时间超过 60 秒,则会被终止并移出缓存。

  • 特点
      - 线程池大小不固定,完全依赖任务的执行情况来决定线程数量。
      - 适合执行大量短期的异步任务。
      - 线程空闲时间超过 60 秒会被回收,因此不会占用系统过多资源。

  • 使用场景:适用于短时间大量任务执行并且希望能快速释放资源的场景。

  • 示例代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CachedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); // 创建一个可缓存的线程池

        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            cachedThreadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
                try {
                    Thread.sleep(2000); // 模拟任务执行耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        cachedThreadPool.shutdown(); // 关闭线程池
    }
}
2.3 newSingleThreadExecutor()

newSingleThreadExecutor() 方法创建一个只有一个线程的线程池。该线程池只有一个工作线程来执行任务,所有任务按照顺序执行,保证任务在同一个线程中被按顺序执行。

  • 特点
      - 线程池只有一个工作线程,可以保证所有任务按照顺序执行。
      - 当唯一的工作线程意外终止时,会创建一个新的线程继续执行任务。
      - 任务队列是无界的,所有提交的任务会依次进入队列等待执行。

  • 使用场景:适用于需要按照顺序执行任务的场景,如需要同步文件或数据库操作。

  • 示例代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadExecutorExample {
    public static void main(String[] args) {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); // 创建一个单线程的线程池

        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            singleThreadExecutor.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
                try {
                    Thread.sleep(2000); // 模拟任务执行耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        singleThreadExecutor.shutdown(); // 关闭线程池
    }
}
2.4 newScheduledThreadPool(int corePoolSize)

newScheduledThreadPool(int corePoolSize) 方法创建一个支持定时和周期性任务执行的线程池。该线程池适用于需要定时或周期性执行任务的场景,如调度系统或定时任务。

  • 特点
      - 可以设置核心线程池的大小(corePoolSize)。
      - 支持定时任务和周期性任务执行。
      - 使用 ScheduledExecutorService 接口的实现类,可以使用 schedule() 方法提交定时任务,使用 scheduleAtFixedRate()scheduleWithFixedDelay() 方法提交周期性任务。

  • 使用场景:适用于需要周期性执行任务或在指定时间点执行任务的场景。

  • 示例代码

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2); // 创建一个支持定时和周期性任务的线程池

        // 提交一个定时任务,延迟 3 秒后执行
        scheduledThreadPool.schedule(() -> {
            System.out.println(Thread.currentThread().getName() + " 执行定时任务");
        }, 3, TimeUnit.SECONDS);

        // 提交一个周期性任务,延迟 1 秒后开始执行,每隔 2 秒执行一次
        scheduledThreadPool.scheduleAtFixedRate(() -> {
            System.out.println(Thread.currentThread().getName() + " 执行周期性任务");
        }, 1, 2, TimeUnit.SECONDS);

        // 提交一个周期性任务,延迟 1 秒后开始执行,当上一个任务执行完毕后,等待 2 秒再执行
        scheduledThreadPool.scheduleWithFixedDelay(() -> {
            System.out.println(Thread.currentThread().getName() + " 执行延迟周期性任务");
        }, 1, 2, TimeUnit.SECONDS);
    }
}

3. 使用 Executors 创建线程池的优点

  • 简化线程池的创建Executors 提供了各种静态工厂方法,使得线程池的创建和使用更加简单方便,避免了手动配置 ThreadPoolExecutor 的麻烦。

  • 提高代码的可读性:通过使用 Executors 提供的方法,代码更加简洁,易于理解和维护。

  • 避免手动管理线程:使用线程池后,开发者不再需要手动管理线程的创建和销毁,提高了资源的利用率,降低了系统的开销。

4. 使用 Executors 的注意事项

  1. 合理选择线程池类型:根据具体的应用场景选择合适的线程池类型,以避免资源浪费和潜在的性能问题。

  2. 避免使用无界队列:在实际使用中,应避免使用无界队列(如 LinkedBlockingQueue),因为它可能会导致内存溢出。可以设置一个合理的队列

大小来控制任务的积压。

  1. 使用 shutdown() 方法关闭线程池:当线程池不再使用时,应该调用 shutdown()shutdownNow() 方法来关闭线程池,避免资源泄漏。

  2. 注意异常处理:在线程池执行任务时,应做好异常处理,防止未捕获的异常导致线程池中的线程终止。

  3. 不要使用 Executors 创建的默认线程池Executors 创建的默认线程池(如 FixedThreadPoolCachedThreadPool)在某些情况下可能存在资源管理问题,如无限队列导致的内存泄漏。因此,建议使用 ThreadPoolExecutor 来显式地创建线程池,并合理配置线程池参数。

5. 总结

Executors 是 Java 并发编程中的一个工具类,为开发者提供了一些便捷的方法来创建和管理线程池。通过 Executors,开发者可以轻松创建不同类型的线程池(如固定大小线程池、缓存线程池、单线程池和定时调度线程池),并根据实际应用场景选择合适的线程池类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Flying_Fish_Xuan

你的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值