JUC(10)线程池的三大方法,7大参数与4种拒绝策略

1.线程池

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务

2.池化技术

程序的运行的本质:占用系统的资源!优化资源的技术 ===> 池化技术。

为什么使用:线程池、连接池、内存池、对象池。。。。创建、销毁。十分浪费资源

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

线程池的好处:

  • 降低资源的浪费

  • 提高响应的速度

  • 方便管理。

3. 三大方法


public class ExecutorsDemo {
    public static void main(String[] args) {
   		 // Executors 工具类、3大方法
        // 1.ExecutorService threadPool = Executors.newSingleThreadExecutor();// 单个线程
        // 2.ExecutorService threadPool = Executors.newFixedThreadPool(5);// 创建一个固定的线程池的大小
        //3.ExecutorService threadPool = Executors.newCachedThreadPool();// 可伸缩的,遇强则强,遇弱则弱

        ExecutorService threadPool = Executors.newCachedThreadPool();// 可伸缩的,遇强则强,遇弱则弱

        try {
            for (int i = 1; i <= 100; i++) {
                // 使用了线程池之后,使用线程池类创建线程
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "---OK");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }
    }
}

4.七大参数

Executors 工具类提供的三种方法本质是调用ThreadPoolExecutor()。通过设置其中的7种参数来定义线程池。

// 本质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.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;
}

5.四种拒绝策略

1.new ThreadPoolExecutor.AbortPolicy() // 队列满了,还有线程进来,不处理这个线程的,抛出异常

2.new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!

3.new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!

4.new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常

6.自定义线程池

举例,银行共有5个窗口(最大线程数),有常开的两个窗口处理业务(核心线程数);候客区(阻塞队列)有三个位置;当两个常开窗口(核心线程)以及候客区(阻塞队列)的位置都有人后,再来客户会开启另外三个窗口;当5个窗口(最大线程)和候客区(阻塞队列)都有人后,再来客户会启动拒绝策略。当窗口(线程)超过设定时间(超时时间)没有业务办理时(未调用)会关闭窗口(释放线程)。

public class ExecutorsDemo01 {
    public static void main(String[] args) {
        // 自定义线程池!工作ThreadPoolExecutor
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy()); //队列满了,尝试去和 最早的竞争,也不会抛出异常!
        try {
            // 最大承载:Deque + max
            // 超过 RejectedExecutionException
            for (int i = 1; i <= 9; i++) {
                // 使用了线程池之后,使用线程池来创建线程
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }
    }
}

7.拓展

问题:池的线程最大值如何去设置!

1、CPU 密集型,几核的计算机就设置为几,可以保存CPU的效率最高!

自动获取计算机CPU处理器个数Runtime.getRuntime().availableProcessors()

2、IO 密集型 —> 判断程序中十分耗IO的线程,根据IO线程数来设定。

比如:15个大型IO线程任务,可以最大线程数为30

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值