了解线程池(二)七大参数和四种拒绝策略

本文详细介绍了线程池的七大核心参数及其作用,并通过示例演示如何手动创建线程池。此外,还深入探讨了四种拒绝策略的实现方式及应用场景,并提供了关于如何合理设置最大线程数的建议。

线程池的七大参数


由于线程池的三大方法都是new ThreadPoolExecutor
所以我们看一下ThreadPoolExecutor

  public ThreadPoolExecutor(int corePoolSize, // 核心线程池大小
int maximumPoolSize, // 最大核心线程池大小
long keepAliveTime, // 超时了没有人调用就会释放
TimeUnit unit, // 超时单位
BlockingQueue<Runnable> workQueue, // 阻塞队列
ThreadFactory threadFactory, // 线程工厂:创建线程的,一般
不用动
RejectedExecutionHandler handle // 拒绝策略) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}

2.手动创建一个线程池

package com.thread.threadpool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Deom01 {
    public static void main(String[] args) {
        // 自定义线程池!工作 ThreadPoolExecutor
        List  list = new ArrayList();
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,           Runtime.getRuntime().availableProcessors(),
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy()); 
        try {
            // 超过 RejectedExecutionException
            for (int i = 1; i <= 20; i++) {
                // 使用线程池来创建线程
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+" ok");
                });
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }

    }
}


3.四大拒绝策略

  • new ThreadPoolExecutor.AbortPolicy() //丢弃任务并抛出RejectedExecutionException异常
  • new ThreadPoolExecutor.CallerRunsPolicy() // 由调用线程(提交任务的线程)处理该任务,这里是main线程去执行
  • new ThreadPoolExecutor.DiscardPolicy() /丢掉任务,不会抛出异常!
  • new ThreadPoolExecutor.DiscardOldestPolicy() //尝试去和最早的竞争,也不会抛出异常!

4. 最大线程到底该如何定义
1、CPU 密集型,几核,就是几,可以保持CPU的效率最高!
2、IO 密集型 最大线程数> 判断你程序中十分耗IO的线程,
3、获取你电脑的CPU的核数
System.out.println(Runtime.getRuntime().availableProcessors());*

### HashMap存储数据过程 虽然给定引用中未提及HashMap存储数据过程,但根据专业知识,HashMap存储数据的过程致如下: 当调用`put(key, value)`方法存储数据时,首先会对`key`的`hashCode()`方法返回值进行次哈希计算,得到一个哈希值。然后,通过这个哈希值与数组长度进行取模运算,确定该键值对在数组中的存储位置(桶位置)。 如果该位置为空,就直接将键值对存储在这个位置。如果该位置已经有元素存在,说明发生了哈希冲突,HashMap会使用链表或红黑树来解决冲突。当链表长度小于8时,采用链表结构,新的键值对会被添加到链表的尾部;当链表长度达到8且数组长度于64时,链表会转换为红黑树,以提高查找效率。当对红黑树进行删除操作,使得树中元素数量小于6时,红黑树又会转换回链表。 ### 线程池参数 线程池参数如下: 1. **核心线程数(corePoolSize)**:线程池中的常驻核心线程数。当提交的任务数小于核心线程数时,线程池会创建新的线程来执行任务,即使此时线程池中存在空闲线程[^1]。 2. **最线程数(maximumPoolSize)**:线程池能够容纳同时执行的最线程数。当提交的任务数超过核心线程数,且工作队列已满时,线程池会创建新的线程,直到线程数达到最线程数[^1]。 3. **空闲线程存活时间(keepAliveTime)**:多余的空闲线程的存活时间。当线程池中的线程数量超过核心线程数,且这些多余的线程空闲时间达到`keepAliveTime`时,它们会被销毁,以节省系统资源[^1]。 4. **时间单位(TimeUnit)**:`keepAliveTime`的时间单位,例如`TimeUnit.SECONDS`表示秒,`TimeUnit.MILLISECONDS`表示毫秒等。 5. **工作队列(workQueue)**:被提交但尚未被执行的任务会存放在工作队列中。常见的工作队列有`ArrayBlockingQueue`(有界队列)、`LinkedBlockingQueue`(无界队列)、`SynchronousQueue`(同步队列)等。例如,`new FixedThreadPool`使用无界队列作为线程池的工作队列[^1]。 6. **线程工厂(ThreadFactory)**:用于创建线程的工厂,通过它可以自定义线程的名称、优先级等属性。 7. **拒绝策略(RejectedExecutionHandler)**:当线程池的工作队列已满,且线程数达到最线程数时,新提交的任务会触发拒绝策略。常见的拒绝策略有`AbortPolicy`(直接抛出异常)、`CallerRunsPolicy`(由调用线程处理该任务)、`DiscardPolicy`(直接丢弃该任务)、`DiscardOldestPolicy`(丢弃工作队列中最老的任务,然后尝试执行新任务)[^1]。 ```java import java.util.concurrent.*; public class ThreadPoolExample { public static void main(String[] args) { // 创建一个线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 核心线程数 5, // 最线程数 60, // 空闲线程存活时间 TimeUnit.SECONDS, // 时间单位 new LinkedBlockingQueue<>(10), // 工作队列 Executors.defaultThreadFactory(), // 线程工厂 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); // 提交任务 for (int i = 0; i < 20; i++) { final int taskId = i; executor.submit(() -> { System.out.println("Executing task " + taskId + " by " + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } // 关闭线程池 executor.shutdown(); } } ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值