JUC练习10——线程池

一,概念

池化技术:线程的运行是占用系统资源的,每个线程的诞生都需要有(创建——初始化——使用——销毁)等步骤,为了避免多次重复的创建和销毁线程利用率,提出了池化技术,先创建好进程放到进程池中,如果要使用进程了就从池里面拿来用,用完之后就还回去。这就是池化技术

传统:创建线程——》使用线程——》销毁进程

池化技术:取出线程)——》使用线程——》归还线程

池化技术优点:降低资源消耗,提高系统的速度,方便对进程的管理

二,线程池

1,三大方法

    /**
     * newSingleThreadExecutor 线程池中就一个线程
     * newFixedThreadPool  通过参数自行定义线程池的大小
     * newCachedThreadPool 根据实际情况自动伸缩线程池的大小
     */
    public static void test6()
    {
        ExecutorService threadPoll1 = Executors.newSingleThreadExecutor();
        ExecutorService threadPoll2 = Executors.newFixedThreadPool(3);
        ExecutorService threadPoll3 = Executors.newCachedThreadPool();

//        for (int i=0;i<10;i++)
//        {
//            threadPoll1.execute(()->
//            {
//                System.out.println(Thread.currentThread().getName()+"——》OK");
//            });
//        }
//        threadPoll1.shutdown();

//        for (int i=0;i<10;i++)
//        {
//            threadPoll2.execute(()->
//            {
//                System.out.println(Thread.currentThread().getName()+"——》OK");
//            });
//        }
//        threadPoll2.shutdown();

        for (int i=0;i<10;i++)
        {
            threadPoll3.execute(()->
            {
                System.out.println(Thread.currentThread().getName()+"——》OK");
            });
        }
        threadPoll3.shutdown();
    }

源码分析:

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

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

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,//21亿
                                      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.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,7大参数,使用原始方法进行线程池的创建

int corePoolSize,//核心线程数
int maximumPoolSize,//最大线程数
long keepAliveTime,//连接保存的时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler) {//拒绝策略
    public static void main(String[] args) {
        test7();
    }
    /**
     * 使用默认的线程池方式进行创建,根据需求去定制
     * 如下配置:核心线程为2,最大线程为5,超时时间为3秒,处理不了的请求放入的队列长度为5,使用的拒绝策略为抛异常
     * 正常情况下是核心的2个线程加上队列来处理请求,如果请求数>核心线程数据+队列长度,会申请新的线程加入处理(当前线程数<最大线程数)
     */
    public static void test7()
    {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        //i<7   i<8   i<5  进行测试
        for (int i=0;i<7;i++)
        {
            threadPoolExecutor.execute(()->
            {
                System.out.println(Thread.currentThread().getName()+"——》OK");
            });
        }
        threadPoolExecutor.shutdown();
    }

3,最大线程数该如何定义

//1,cpu密集型  获取cpu的核数作为线程的最大数  Runtime.getRuntime().availableProcessors()
//2,IO密集型 判断你的程序中十分耗IO的线程有几个,最大线程数大于它即可

 

posted @ 2022-02-01 13:53  陈建江  阅读(49)  评论(0编辑  收藏  举报