如何自定义线程池

1 篇文章 0 订阅

面试题:一个线程池,core 7;max 20;queue:50;100 个并发进来如何分配:

# 7个会立即执行,50个会进入队列,再开13个进行执行,剩余30个使用拒绝策略

线程池:3 大方法,7 大参数,4 种拒绝策略

池化技术

程序的运行,本质:占用系统的资源!优化资源的使用!

线程池、连接池、内存池、对象池。。。创建、销毁 => 十分浪费资源

池化技术:事先准备好一些资源,有人要用,就来拿,用完之后归还

线程池的好处

1、降低资源的损耗

通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗

2、提高响应的速度

当线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行

3、方便管理

线程池会根据当前系统特点,对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使用线程池可以统一分配

线程复用,可以控制最大并发数,管理线程

线程池:3 大方法

package com.xoste.pool;

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

/**
 * @author 小斯特
 * @date 2021/11/23 16:27
 * Executors 工具类、3大方法
 */
public class ExecutorsDemo {
    public static void main(String[] args) {
        // 单个线程
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 创建一个固定的线程池大小
        ExecutorService threadPool2 = Executors.newFixedThreadPool(5);
        // 可伸缩的,遇强则强,遇弱则弱
        ExecutorService threadPool3 = Executors.newCachedThreadPool();
        try {
           for (int i = 0; i < 100; i++) {
               threadPool3.execute(() -> {
                   System.out.println(Thread.currentThread().getName() + " ok");
               });
           }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool3.shutdown();
        }
    }
}

线程池:7大参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CeaP33zo-1646724702419)(JUC.assets\image-20211123162036611-1637673805309-1637673810285.png)]

// 单线程的线程池,后台从队列里面获取任务,挨个执行
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
// 固定大小,core=max,都不可回收
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
// core=0,所有都可回收
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
// 定时任务的线程池
 public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

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

在这里插入图片描述

在这里插入图片描述

4 种拒绝策略

在这里插入图片描述

默认拒绝策略

在这里插入图片描述

手动创建一个线程池

package com.xoste.pool;

import java.util.concurrent.*;

/**
 * @author 小斯特
 * @date 2021/11/23 16:27
 * Executors 工具类、3大方法
 *
 *  // 银行满人了,还有人进来,不处理这个人,抛异常
 *  new ThreadPoolExecutor.AbortPolicy()
 *  //既不抛弃任务也不抛出异常,而是将某些任务回退到调用者,让调用者去执行它(哪来的,去哪里)
 *  new ThreadPoolExecutor.CallerRunsPolicy()
 *  // 队列满了,不会抛出异常!
 *  new ThreadPoolExecutor.DiscardPolicy()
 *  // 队列满了,直接丢弃最老的任务,重新尝试执行当前任务
 *  new ThreadPoolExecutor.DiscardOldestPolicy()
 *
 */
public class ExecutorsDemo {
    public static void main(String[] args) {
        // 自定义线程池!工作 ThreadPoolExecutor
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,// 核心线程池大小
                5,// 最大核心线程池大小
                3,// 超时了没有人就会释放(存活时间)
                TimeUnit.SECONDS,// 超时单位
                new LinkedBlockingQueue<>(3),// 阻塞队列容器
                Executors.defaultThreadFactory(),// 线程工厂,创建线程,一般不用动
                // 队列满了,直接丢弃最老的任务,重新尝试执行当前任务
                new ThreadPoolExecutor.DiscardOldestPolicy() // 拒绝策略);
        try {
           for (int i = 0; i < 9; i++) {
               threadPool.execute(() -> {
                   // 使用了线程池之后,使用线程池来创建线程
                   System.out.println(Thread.currentThread().getName() + " ok");
               });
           }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
             // 线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }
    }
}

小结–拓展

池的最大的大小如何去设置!

了解:CPU密集型,IO密集型(调优)

// 最大线程到底该如何定义
// 1.CPU 密集型,几核,就是几,可以保持 CPU 的效率最高!
// 2.IO 密集型 > 判断程序中,十分耗 IO 的线程,
// 程序 15个大型任务 IO十分占用资源

// 获取  CPU 的核数
System.out.println(Runtime.getRuntime().availableProcessors());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值