线程池(重点)

Posted 偶像java练习生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池(重点)相关的知识,希望对你有一定的参考价值。

线程池

线程池:三大方法,7大参数,4 种拒绝策略
1.池化技术
程序的运行,本质:占用系统的资源!我们就要优化资源的使用! =》池化技术

线程池,jdbc连接池,内存池,对象池… 创建,销毁,十分浪费资源

  1. 最小的池
  2. 最大的池

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

2.如果事先准备2 个,则默认就只有2 个

线程池的好处

  1. 降低资源的消耗,
  2. 提高响应的速度
  3. 方便管理

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

线程池必会

三大方法

在这里插入图片描述

package com.pool;


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

/**
 * Executors:工具类,3 大方法
 * 发音:一刻贼可特死
 * 使用线程池之后,使用线程池来创建线程
 */
public class Demo01 {


    public static void main(String[] args) {
        //得到一个单一的线程池
        //ExecutorService threadPool = Executors.newSingleThreadExecutor();

        //得到一个固定的值 5 个线程数
        ExecutorService executorService = Executors.newFixedThreadPool(5);

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

        try {
            for (int i = 0; i < 10; i++) {
                //使用线程池之后,使用线程池来创建线程
                executorService.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.isShutdown();
        }
        // 线程池用完,程序结束,关闭线程池



    }
}

输出结果:
pool-1-thread-1ok
pool-1-thread-4ok
pool-1-thread-3ok
pool-1-thread-3ok
pool-1-thread-2ok
pool-1-thread-1ok
pool-1-thread-3ok
pool-1-thread-4ok
pool-1-thread-5ok
pool-1-thread-2ok

7大参数
源码分析:

newSingleThreadExecutor:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

newFixedThreadPool:

   public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newCachedThreadPool:

 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,//21 亿 电脑一定会OOM
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

三个方法调用的本质还是: 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;
    }

场景:银行办理业务
在这里插入图片描述
超时不候:
在这里插入图片描述

手动创建一个线程池

四种拒绝策略

package com.pool;

import java.util.concurrent.*;

/**
 *
 * 银行办理业务场景,四种拒绝策略
 * new ThreadPoolExecutor.AbortPolicy() // 银行满了,还有人进来,不处理这个热的,抛出异常
 * new ThreadPoolExecutor.CallerRunsPolicy // 哪里来的去哪里! main 线程帮忙执行
 * new ThreadPoolExecutor.DiscardPolicy   //队列满了,丢掉任务,不会抛出异常!
 * new ThreadPoolExecutor.DiscardOldestPolicy //队列满了,尝试和最早的竞争,也不会抛出异常
 */
public class Demo2 {


    public static void main(String[] args) {
        //自定义线程池! 工作 ThreadPoolExecutor
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),//触发最大队列
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy());//银行满了,候客区满了,但是还有人进来,就不处理这个人的了,抛出异常!



        try {
            //最大承载: deque数 + max
            //如果超过deque 数 加 max 则 java.util.concurrent.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();
        }
    }


}

池的最大大小如何设置(调优)

  1. CPU 密集型 几核,就是几 条,可以保证CPU 效率最高! (8核的, 8条线程同时执行!)
        //获取CPU 核数
        System.out.println(Runtime.getRuntime().availableProcessors());//输出结果 8 

在这里插入图片描述

  1. IO 密集型

判断你程序中十分耗耗IO 的线程! 一般设置两倍
假如程序有15 个大型任务,io 十分占资源!,就设置30个

以上是关于线程池(重点)的主要内容,如果未能解决你的问题,请参考以下文章

线程池(重点)

重点知识学习(8.4)--[线程池 , ThreadLocal]

线程池与并行度

Java——线程池

Motan在服务provider端用于处理request的线程池

Java线程池详解