• 【线程池、有返回值的线程池、线程池监控】


    什么是线程池?

    就是提前创建好了几个线程给他放到一个容器里,有任务需要执行时,出来一个线程执行任务,任务执行完了不销毁线程,然后放回去,等待下一次任务到来。

    线程池的好处

    1. 降低创建线程和销毁线程的性能开销
    2. 提高响应速度,当有新任务需要执行是不需要等待线程创建就
      可以立马执行
    3. 合理的设置线程池大小可以避免因为线程数超过硬件资源瓶颈
      带来的问题

    Java提供的四种线程池

    newFixedThreadPool:
    固定大小的线程池,每次有任务就创建一个线程,直到线程达到线程池的最大值,后面的任务会放到一个队列里,等待线程空闲的时候执行

    public class PoolDemo implements Runnable{
        public static void main(String[] args) {
            ExecutorService pool = Executors.newFixedThreadPool(3);
            for (int i = 0; i <100 ; i++) {
                pool.execute(new PoolDemo() {
                });
    
            }
            pool.shutdown();
    
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    代码结果
    newFixedThreadPool
    可以很清楚看见只有3个线程在运行,这就是线程池的好处,循环利用已有的线程。

    newSingleThreadExecutor:
    java线程池中单一的线程池。表示是一个线程池,可以添加多个子线程,但是只有一个线程能运行,当前线程执行完了后下一个添加进来的线程才能运行。单一的线程池,该线程池中每时每刻只有一个线程能运行。添加进入的线程必须等待当前执行的线程执行完了后,才能执行(依照先进先出)

    public class PoolDemo implements Runnable{
        public static void main(String[] args) {
            ExecutorService pool = Executors.newSingleThreadExecutor();
            for (int i = 0; i <100 ; i++) {
                pool.execute(new PoolDemo() {
                });
            }
            pool.shutdown();
    
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    newSingleThreadExecutor
    这个就是只有一个线程。

    newCachedThreadPool:
    动态伸缩线程池,任务到来,回收空闲的线程,若没有空闲的,则新建

    public class PoolDemo implements Runnable{
        public static void main(String[] args) {
            ExecutorService pool = Executors.newCachedThreadPool();
            for (int i = 0; i <100 ; i++) {
                pool.execute(new PoolDemo() {
                });
            }
            pool.shutdown();
    
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    newCachedThreadPool
    newScheduledThreadPool:
    周期性线程池

    public class PoolDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
            scheduledThreadPool.schedule(new Runnable() {
                @Override
                public void run() {
                    // 延迟3秒执行
                    System.out.println("延迟3秒执行,当前线程:" + Thread.currentThread().getName() + "当前任务时间:"
                            + DateFormat.getTimeInstance().format(new Date()));
                }
            }, 3, TimeUnit.SECONDS);
            scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    // 延迟1秒,每隔3秒执行
                    System.out.println("延迟1秒,每隔3秒执行,当前线程:" + Thread.currentThread().getName() + "当前任务时间:"
                            +DateFormat.getTimeInstance().format(new Date()));
                }
            }, 1, 3, TimeUnit.SECONDS);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    newScheduledThreadPool

    如果大家查看源码会发现,前三个里面其实都是new ThreadPoolExecutor

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

    区别只是这个ThreadPoolExecutor后面参数不一样而已
    在这里插入图片描述根据注释来看,括号内的参数我们不难理解。

       public ThreadPoolExecutor(int corePoolSize,//池中要保留的线程数,也就是线程的数量
                                  int maximumPoolSize,//最大线程数
                                  long keepAliveTime,//存活时间
                                  TimeUnit unit,//存活时间的单位
                                  BlockingQueue<Runnable> workQueue)//用于在执行任务之前保留任务的队列
                                   {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    有返回值的线程池

    public class CallableFutureDemo implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("hello");
            Thread.sleep(3000);
            return "你好";
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executorService = Executors.newFixedThreadPool(1);
            CallableFutureDemo callableFutureDemo = new CallableFutureDemo();
            FutureTask futureTask  = (FutureTask)executorService.submit(callableFutureDemo);
            System.out.println(futureTask.get());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    线程池监控

    自己新建一个Exectors ,然后去把源码复制一个

    public class Exectors {
        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolSelf(nThreads, nThreads,
                    0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后新建一个ThreadPoolSelf继承ThreadPoolExecutor,重写shutdown,beforeExecute,afterExecute。

    public class ThreadPoolSelf extends ThreadPoolExecutor {
        public ThreadPoolSelf(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }
    
        @Override
        public void shutdown() {
            super.shutdown();
        }
    
        @Override
        protected void beforeExecute(Thread t, Runnable r) {
            System.out.println(Thread.currentThread().getName()+"线程开始时间:"+ DateFormat.getTimeInstance().format(new Date()));
        }
    
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            System.out.println("初始线程数:"+this.getPoolSize());
            System.out.println("核心线程数:"+this.getCorePoolSize());
            System.out.println("正在执行的任务数量:"+this.getActiveCount());
            System.out.println("已经执行的任务数量:"+this.getCompletedTaskCount());
            System.out.println("任务总数:"+this.getTaskCount());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    然后就可以把我们需要的信息打印出来了。

    public class PoolDemo implements Runnable{
        public static void main(String[] args) {
            ThreadPoolExecutor pool = (ThreadPoolExecutor) Exectors.newFixedThreadPool(3);
            //可以提前预热所有核心线程
            pool.prestartAllCoreThreads();
            for (int i = 0; i <100 ; i++) {
                pool.execute(new PoolDemo() {
                });
            }
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    CMake Tutorial 巡礼(2)_添加库
    PyTorch常用代码段合集
    VirtualBox安装Centos
    不到20W纯电SUV提回家,到店实拍2022款奇瑞大蚂蚁
    盘点|国内5款主流低代码开发平台介绍
    python调用32位的ControlCan.dll实现can报文的收发
    逻辑回归揭秘: 从分类原理到机器学习实践
    SAP固定资产模块的表
    自定义弹窗(含生成zxing二维码功能)看这一篇就够了
    新研一暑假计划
  • 原文地址:https://blog.csdn.net/Relaxaaa/article/details/125373105