为什么要使用线程池?

笔者带着读者们的疑惑查阅古今著名经典:《黄帝内经》,《四书五经》,《本草纲目》,《方志鹏的spring cloud初级卷》等;

得到 诸子百家的解答:
1:系统资源有限,每个人都是手动创建线程,当系统运行起来,所有线程都在疯狂抢占资源,无组织无纪律,有可能教室就炸锅啦(这场景我学生时代历历在目);
2:开销大,又是创建又是销毁(底层原理俺不懂-_-);

到此,知道了为什么,理解东西就更深刻了。

经过查阅当代所有文献,以及笔者对所有同行同事的跪舔以及不耻下问,得出,使用这个玩意儿:ThreadPoolExecutor。Java线程池就是为了最大化高并发带来的性能提升,并最小化手动创建线程的风险,将多个线程统一在一起管理。

上代码:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,  TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

corePoolSize:指定了线程池中的线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去;

maximumPoolSize:指定了线程池中的最大线程数量,这个参数会根据你使用的workQueue任务队列的类型,决定线程池会开辟的最大线程数量;

keepAliveTime:当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁;

unit:keepAliveTime的单位

workQueue:任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种;

threadFactory:线程工厂,用于创建线程,一般用默认即可;

handler:拒绝策略;当任务太多来不及处理时,如何拒绝任务;

以上参数配置不作详细介绍,里面配置类型很多,各位自行查阅(主要是小弟棋艺不精~~)

来例子:
案例1:三个线程,最大线程数是4,先执行第一个线程,进入睡眠,然后执行新建第二个线程

package com.china.great.amos.chinagreatblog.thread;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Liu HongYang
 * @DateTime: 2020/5/18 10:55 下午
 * @Description: TODO
 */
public class ThreadPools {

    public static void main(String[] args) {

        ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2));
        // 第1个任务
        pool.execute(() -> {
            try {
                Thread.sleep(5 * 1000);// 5秒
                System.out.println("--001--" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 第2个任务
        pool.execute(() -> System.out.println("--002--" + Thread.currentThread().getName()));
        // 第3个任务
       /* pool.execute(() -> System.out.println("--003--" + Thread.currentThread().getName()));
        // 第4个任务
        pool.execute(() -> System.out.println("--004--" + Thread.currentThread().getName()));
        // 第5个任务
        pool.execute(() -> System.out.println("--005--" + Thread.currentThread().getName()));*/

    }

}

结果为:

java spring 线程变量 spring使用线程池_System

案例2:一共两个线程,最大是3,队列数是2,001跟002一开始就占满了两个核心线程,线程003跟线程0044就进入了队列,所以先执行完线程0022,然后执行队列里面的003跟004,最后是001

package com.china.great.amos.chinagreatblog.thread;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Liu HongYang
 * @DateTime: 2020/5/18 10:55 下午
 * @Description: TODO
 */
public class ThreadPools {

    public static void main(String[] args) {

        ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2));
        // 第1个任务
        pool.execute(() -> {
            try {
                Thread.sleep(5 * 1000);// 5秒
                System.out.println("--001--" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 第2个任务
        pool.execute(() -> {
            try {
                Thread.sleep(4 * 1000);// 5秒
                System.out.println("--002--" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 第3个任务
        pool.execute(() -> System.out.println("--003--" + Thread.currentThread().getName()));
        // 第4个任务
        pool.execute(() -> System.out.println("--004--" + Thread.currentThread().getName()));
        // 第5个任务
        /*pool.execute(() -> System.out.println("--005--" + Thread.currentThread().getName()));*/

    }

}

结果:

java spring 线程变量 spring使用线程池_System_02


案例3:把参数LinkedBlockingQueue改为1,主要是因为一共只有两个线程,001跟002马上占满,队列只允许1个,003进入队列,实际运行线程=2,小于maximumPoolSize最大线程数3,所以004新开一个线程

结果为:

java spring 线程变量 spring使用线程池_System_03