多线程:初始化线程池

初始化线程池主要有两种常见的方式,分别是使用 Executors 工具类和手动创建 ThreadPoolExecutor 实例。

使用 Executors 工具类

Executors 是 Java 提供的一个线程池工具类,它提供了一些静态工厂方法来创建不同类型的线程池,使用起来较为方便。

1. 创建固定大小的线程池

使用 Executors.newFixedThreadPool(int nThreads) 方法可以创建一个固定大小的线程池,线程池中的线程数量始终保持为指定的大小。

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

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

        // 提交任务到线程池
        for (int i = 0; i < 5; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + " is completed.");
            });
        }

        // 关闭线程池
        executorService.shutdown();
    }
}
2. 创建单线程线程池

使用 Executors.newSingleThreadExecutor() 方法可以创建一个只有一个线程的线程池,所有任务会按照提交的顺序依次执行。

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

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

        // 提交任务到线程池
        for (int i = 0; i < 5; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + " is completed.");
            });
        }

        // 关闭线程池
        executorService.shutdown();
    }
}
3. 创建可缓存的线程池

使用 Executors.newCachedThreadPool() 方法可以创建一个可缓存的线程池,线程池中的线程数量会根据任务的数量动态调整。如果线程池中的线程在 60 秒内没有被使用,会被自动回收。

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

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("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + " is completed.");
            });
        }

        // 关闭线程池
        executorService.shutdown();
    }
}
使用 Executors 工具类的优缺点
  • 优点:使用简单,代码量少,适合快速开发和一些简单的场景。
  • 缺点:可能会导致资源耗尽问题。例如,newCachedThreadPool 允许创建的线程数量没有上限,在任务数量过多时可能会创建大量线程,导致系统资源耗尽;newFixedThreadPoolnewSingleThreadExecutor 使用的是无界队列,当任务提交速度过快时,队列可能会无限增长,也会导致内存溢出。

手动创建 ThreadPoolExecutor 实例

为了避免 Executors 工具类可能带来的资源耗尽问题,建议手动创建 ThreadPoolExecutor 实例,通过自定义线程池的参数来更好地控制线程池的行为。

import java.util.concurrent.*;

public class ThreadPoolExecutorExample {
    public static void main(String[] args) {
        // 核心线程数
        int corePoolSize = 2;
        // 最大线程数
        int maximumPoolSize = 5;
        // 线程空闲时间
        long keepAliveTime = 60;
        // 时间单位
        TimeUnit unit = TimeUnit.SECONDS;
        // 任务队列
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(10);
        // 线程工厂
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        // 拒绝策略
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

        // 创建线程池
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler
        );

        // 提交任务到线程池
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executorService.submit(() -> {
                System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + " is completed.");
            });
        }

        // 关闭线程池
        executorService.shutdown();
    }
}
手动创建 ThreadPoolExecutor 实例的优点
  • 可以根据具体的业务需求灵活配置线程池的参数,如核心线程数、最大线程数、任务队列、线程空闲时间、线程工厂和拒绝策略等,避免资源耗尽问题,提高系统的稳定性和性能。

建议优先使用手动创建 ThreadPoolExecutor 实例的方式来初始化线程池。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值