JAVA线程池的初始化方法

Executors.newCachedThreadPool()

//创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
newCachedThreadPool将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,使用的SynchronousQueue,也就是说来了任务就创建线程运行,当线程空闲超过60秒,就销毁线程。

Executors.newSingleThreadExecutor()

//创建容量为1的缓冲池
newSingleThreadExecutor将corePoolSize和maximumPoolSize都设置为1,也使用的LinkedBlockingQueue。

Executors.newFixedThreadPool(int)

//创建固定容量大小的缓冲池
newFixedThreadPool创建的线程池corePoolSize和maximumPoolSize值是相等的,它使用的LinkedBlockingQueue。

### 正确初始化 Java 线程池以避免 NullPointerException 在 Java 中,线程池的正确初始化对于程序的稳定性和性能至关重要。如果未正确初始化线程池,可能会引发 `NullPointerException` 或其他运行时错误。 #### 1. 使用 ThreadPoolExecutor 初始化线程池 当使用 `ThreadPoolExecutor` 创建自定义线程池时,需确保传递给它的参数均有效且不为空。以下是常见的构造函数签名: ```java public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler); ``` - **corePoolSize 和 maximumPoolSize**: 这两个参数决定了核心线程数和最大线程数,应为正整数值。 - **workQueue**: 工作队列不应为 null;通常可以选择 `LinkedBlockingQueue`, `ArrayBlockingQueue` 或者 `SynchronousQueue` 等实现[^1]。 - **threadFactory**: 如果提供,则用于创建新线程,默认情况下可以省略。 - **handler**: 当任务被拒绝时使用的处理器,例如 DiscardOldestPolicy 可以防止因队列满而抛出异常。 示例代码如下: ```java import java.util.concurrent.*; public class ThreadPoolExample { public static void main(String[] args) { BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(10); // 队列大小设为10 RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy(); ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 核心线程数 4, // 最大线程数 60L, // 超过核心线程闲置时间 TimeUnit.SECONDS, queue, Executors.defaultThreadFactory(), handler); try { for (int i = 0; i < 15; i++) { executor.execute(() -> System.out.println(Thread.currentThread().getName())); } } finally { executor.shutdown(); } } } ``` #### 2. ForkJoinPool 的初始化注意事项 ForkJoinPool 是一种特殊的线程池,适用于分治算法的任务分解与合并操作。其默认构造器会根据可用 CPU 数量来决定并行级别[^2]。然而,在某些复杂场景下可能需要手动调整配置。 推荐做法是通过指定初始参数实例化对象,比如下面的例子展示了如何设定固定的并行度以及定制化的工厂模式生产 worker threads: ```java import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; class SumTask extends RecursiveTask<Integer> { private final int[] array; private final int start; private final int end; public SumTask(int[] array, int start, int end){ this.array=array; this.start=start; this.end=end; } @Override protected Integer compute(){ if(end-start<=3){return sumDirectly();} else{ int mid=(start+end)/2; SumTask left=new SumTask(array,start,mid); SumTask right=new SumTask(array,mid,end); invokeAll(left,right); return left.join()+right.join(); } } private int sumDirectly(){ int result=0; for(int i=start;i<end;i++)result+=array[i]; return result; } } public class Main { public static void main(String[] args)throws Exception{ int[] data={1,2,3,4,5}; ForkJoinPool customPool=new ForkJoinPool(8,ForkJoinPool.defaultForkJoinWorkerThreadFactory,null,true); SumTask task=new SumTask(data,0,data.length); System.out.println(customPool.invoke(task)); } } ``` 上述代码片段中设置了固定数量的工作线程(此处为8),并且启用了异步预取功能以便更好地利用资源[^3]。 #### 总结 为了预防 NPE 发生,开发者应当仔细校验传入到线程池构建过程里的每一个组件是否合法合规,并考虑边界条件下的行为表现。此外,合理选用合适的拒绝策略也能增强系统的健壮性[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值