精华内容
下载资源
问答
  • 一丶什么线程池(1)博主在听到线程池三个字的时候第一个想法就是数据库连接池,回忆一下,我们在学JavaWeb的时候怎么理解数据库连接池的,数据库创建连接和关闭连接是一个比较耗费资源的事情,对于那些数量多且时间...

    一丶什么是线程池

    (1)博主在听到线程池三个字的时候第一个想法就是数据库连接池,回忆一下,我们在学JavaWeb的时候怎么理解数据库连接池的,数据库创建连接和关闭连接是一个比较耗费资源的事情,对于那些数量多且时间短暂的任务,会导致频繁获取和释放连接,这样使得处理事务的效率大大降低,多以我们创建一个连接池,里面放了指定数目的连接,当应用需要数据库连接的时候去里面获取,使用完毕后再放到连接池里,这样就避免了重复的获取连接和释放连接,至于要获取什么样的连接池我们可以根据应用的特征,设置参数来决定。(2)线程池和连接池很相似,线程池的产生是为了避免重复的创建线程和回收线程。本着存在即合理,存在即有优点的理念(这个说法不普遍适用),线程池有如下三个优点:

    ①降低资源消耗。通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。②提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。③提高线程的可管理性。线程是稀缺资源,如果入限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控。


    二丶ThreadPoolExecutor的使用

    ThreadPoolExecutor是线程池的最核心的一个类,所以要了解线程池我们先来看看ThreadPoolExecutor类的实现。本着先学开车后学修车的理念,我们先通过范例来学习一下ThreadPoolExecutor的使用(以后对JDK源码框架的学习都会本着这个原则)。

    c91079d0a97d49c334d8d34bea9722a0.png

    输出:

    822ce13572b77a90ba5761374c25f409.png

    以上的范例就是ThreadPoolExecutor的简单应用,首先需要创建一个任务类MyTask ,其次在主方法里创建ThreadPoolExecutor对象,接着用for循环来模拟运行多个线程,然后execute方法执行,最后调用shutdown方法结束。

    上面代码的实现和我们往常实现多线程有些区别,我们往常使用:

    94e4023daa41b87958c707d5db3068aa.png

    来创建一个线程执行任务,在应用ThreadPoolExecutor时,我们不再自己创建,而是使用线程池为我们创建的线程。

    在创建线程池ThreadPoolExecutor对象时,有很多个构造参数,通过注释我们可以了解到,这些参数就是用来设置线程池的特征的。

    三丶从源码来看ThreadPoolExecutor

    1)ThreadPoolExecutor结构:

    f0a818ab6718484b8436387ee16a52a0.png

    2)线程池处理任务处流程:

    知道了ThreadPoolExecutor的继承关系后我们来了解一下ThreadPoolExecutor的设计结构和思想,这对我们后面理解ThreadPoolExecutor的源码有很大的帮助:

    94bfb2c229768f1b2d5d843b2b8bae61.png

    (对队列的判断应该在线程池内部)

    上面的这张图应该就能大概的描述ThreadPoolExecutor的实现了,同时也能够理解ThreadPoolExecutor的构造参数了。

    线程池在创建的时候会设置CorePoolSize,maximumPoolSize,workQueue等几个重要参数,CorePoolSize指的是核心线程池的大小,maximumPoolSize指的是线程池的线程数最大值,workQueue为线程池指定的阻塞队列。处理流程:

    1. 主线程执行execute方法,提交任务到线程池,线程池判断核心线程池中的线程是否都在工作,如果不是则创建一个线程来执行新任务,如果都在工作,进入下一步。
    2. 判断工作队列是否已满,如果不满,则将新任务加入到阻塞队列中,如果满了进入下一步。
    3. 判断线程池中线程数是否小于maximumPoolSize,如果小于,创建新的线程来处理新任务,否则交给饱和策略。

    3)源码:接下来我们跟着方法的执行流程来跟源码:源码从哪里开始跟?当然是从execute方法开始啦,毕竟这个是执行的开端呀(博主跟源码还是喜欢这样,这样慢慢跟下去,不太喜欢直接看构造,字段,方法,等看到了字段属性再跟下去看)。


    3.1 execute:

    267d2a68e3e05a60a2dcd4b9ab09ac55.png

    相信这个方法已经不要我再多作什么赘述了吧(捂嘴笑.jpg)。

    这里我们再将ThreadPoolExecutor的一些字段列一下:

    cfb7a6c03dca578c0d1c32638cee9102.png

    如果没有对照源码看博文的小伙伴可能会有很多疑问,相信你打开源码再看我的方法注释会更好的理解!


    3.2 addWorker:看了上面的execute方法,相信我们可以看出来addWorker方法也算是核心了,addWorker方法担任了所有的将任务交给线程的操作:

    085957a3320903db6262a9a3cc094b4a.png

    从上面的代码我们可以发现,当任务交给线程执行的时候并不是直接的交给线程,线程池创建线程后会将线程封装成工作线程Worker,Worker工作完后还会继续去工作队列中获取任务来执行。


    3.3 Worker类:

    4dadb65b49294657af361439380e10e0.png

    我们可以从下面这段Worker类的Run方法中窥到这一点:

    jdk1.8和1.7有很大的改动,有兴趣的朋友可以去对比一下

    d2a5e6d7155c015db170a72e10595e42.png
    8743e3b2bbd06235ac5dce5b63c99e39.png

    3.4 submit:

    既然讲到了execute方法,怎么能少了submit方法,当我们执行一个任务的时候,有的时候需要返回值,这个时候我们就需要用到submit方法了。

    其实我们通过源码可以发现submit方法内部也是调用execute方法,当调用submit方法的时候我们可以收到一个Future对象,我们可以调用Future对象的get方法来获得它的返回值。

    注:我在ThreadPoolExecutor中找submit方法的时候没找到,然后才发现ThreadPoolExecutor是直接继承他的父类AbstractExecutorService的。

    ababf5f1690e026e2d5ec2b02ca16320.png

    从上面的代码我们可以看出将任务包装成一个RunnableFuture对象,然后将这个对象用execute执行。如果看过我上面推荐的博文,读者应该知道Callable和和Runnable的区别了:是否有返回值。

    关于这个Future的结构我们来理一下:FutureTask→(实现)RunnableFuture→(继承)Runnable,Future

    我们可以看看newTaskFor方法:

    5106316eaf87d32085da9502ced0d70f.png

    它的底层其实就是new一个FutureTask对象而已,所以FutureTask才是真正的实现类哦!关于FutureTask的实现,我们会专门抽出时间去整理!


    3.5shutdown和shutdownNow:我们可以通过shutdown和shutdownNow方法来关闭线程池,shutdown方法通过遍历工作线程HashSet,将运行状态(ctl)这设置为SHUTDOWN并调用interrupt方法中断所有线程,shutdownNow同样遍历所有线程,将将运行状态(ctl)这设置为STOP,并调用interrupt方法中断所有线程。

    e7d80878e5b4b6899b34746a0ee8b6dd.png
    fa401309c16f1ee6134618346478af29.png

    3.6 RejectedExecutionHandler:最后我们来看看这个饱和策略,当线程和队列都满了过后,表明这个线程池处于饱和的状态,那么我们必须要采取一定的措施来处理这些任务,在默认的情况下我们会执行AbortPolicy,表示无法处理任务,抛出异常。同时JDK提供了以下的几种策略:

    • AbortPolicy:直接抛出异常
    • CallerRunsPolicy:用调用者的线程来执行任务
    • DiscardOldestPolicy:丢弃队列里最近的任务,并执行这个任务
    • DiscardPolicy:丢弃,不处理

    我们也可以实现RejectedExecutionHandler接口进行自定义操作,例如有的时候我们需要将这种异常记录到日志当中,这个时候我们就需要自定义了!

    总结:通过对线程池的学习,自己又了解到不少自己不知道的知识,例如Future接口等,也通过学习,发现一些容器和锁真的很常见,自己平时应用的时候很少碰见,当然,大师的编程水平也值得我们这些小民学习!

    展开全文
  • 首先看源码中的一句注释: A pool that is no longer ...如果程序中不再持有线程池的引用,并且线程池中没有线程时,线程池将会自动关闭线程池自动关闭的两个条件:1、线程池的引用不可达;2、线程池中没有线程;...

    首先看源码中的一句注释:

    A pool that is no longer referenced in a program and has no remaining
    threads will be shutdown automatically.

    如果程序中不再持有线程池的引用,并且线程池中没有线程时,线程池将会自动关闭。

    线程池自动关闭的两个条件:1、线程池的引用不可达;2、线程池中没有线程;
    这里对于条件2解释一下,线程池中没有线程是指线程池中的所有线程都已运行完自动消亡。

    然而我们常用的FixedThreadPool的核心线程没有超时策略,所以并不会自动关闭。所以我们在使用fixedThrePool核心线程时需要适当调用Shutdown方法,防止内存溢出。

    public class TExt {
        public static void main(String[] args) {
            ExecutorService eS = Executors.newFixedThreadPool(2);
            MyThread myThread = new MyThread();
            eS.submit(myThread);
            eS.submit(myThread);
            //eS.shutdown();
        }
    }
    
    
    public class MyThread implements Runnable{
        Object o=new Object();
    
    
        @Override
        public void run() {
            synchronized (o){
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("我执行了" + Thread.currentThread().getName() + " :" + i);
                }
            }
        }
    }
    

    如上图所示代码运行,如果不调用Shutdown方法,程序将一直处于运行状态。

    可以自动关闭的是CachedThreadPool 线程。

    CachedThreadPool的线程keepAliveTime 默认为 60s ,核心线程数量为 0 ,所以不会有核心线程存活阻止线程池自动关闭。 详见 线程池之ThreadPoolExecutor构造 ,为了更快的模拟,构造后将 keepAliveTime 修改为1纳秒,相当于线程执行完马上会消亡,所以线程池可以被回收。实际开发中,如果CachedThreadPool 确实忘记关闭,在一定时间后是可以被回收的。

    测试一下将上面的main方法代码修改为:

    public class TExt {
        public static void main(String[] args) {
            ExecutorService eS = Executors.newCachedThreadPool();
            ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) eS;
            // 为了更好的模拟,动态修改为1纳秒
            threadPoolExecutor.setKeepAliveTime(1, TimeUnit.NANOSECONDS);
            MyThread myThread = new MyThread();
            eS.submit(myThread);
            eS.submit(myThread);
            //eS.shutdown();
        }
    }
    

    因为动态修改了关闭时间为1纳秒,所以线程池结束后就直接关闭了。

    展开全文
  • 一、使用线程池时候当程序结束时候记得调用shutdown关闭线程池 日常开发中为了便于线程的有效复用,线程池是经常会被用的工具,然而线程池使用完后如果不调用shutdown会导致线程池资源一直不会被释放。下面通过简单...

    一、使用线程池时候当程序结束时候记得调用shutdown关闭线程池

    日常开发中为了便于线程的有效复用,线程池是经常会被用的工具,然而线程池使用完后如果不调用shutdown会导致线程池资源一直不会被释放。下面通过简单例子来说明该问题。

    1、问题复现

    下面通过一个例子说明当不调用线程池对象的shutdown方法后,当线程池里面的任务执行完毕后主线程这个JVM不会退出。

    public class TestShutDown {
    
            static void asynExecuteOne() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute one ---");
                }
            });
        }
        
        static void asynExecuteTwo() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute two ---");
                }
            });
        }
        
    
        public static void main(String[] args) {
           //(1)同步执行
            System.out.println("---sync execute---");
           //(2)异步执行操作one
            asynExecuteOne();
           //(3)异步执行操作two
            asynExecuteTwo();
           //(4)执行完毕
            System.out.println("---execute over---");
        }
    }
    

    如上代码主线程里面首先同步执行了操作(1)然后执行操作(2)(3),操作(2)(3)使用线程池的一个线程执行异步操作,我们期望当主线程和操操作(2)(3)执行完线程池里面的任务后整个JVM就会退出,但是执行结果却如下:

    img

    右上角红色方块说明JVM进程还没有退出,Mac上执行ps -eaf|grep java后发现Java进程还是存在的,这是什么情况那?修改操作(2)(3)在方法里面添加调用线程池的shutdown方法如下代码:

                static void asynExecuteOne() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute one ---");
                }
            });
            
            executor.shutdown();
        }
        
        static void asynExecuteTwo() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute two ---");
                }
            });
            
            executor.shutdown();
        }
    

    在执行就会发现JVM已经退出了,使用ps -eaf|grep java后发现Java进程以及不存在了,这说明只有调用了线程池的shutdown方法后当线程池任务执行完毕后线程池资源才会释放。

    2、问题分析

    下面看下为何如此那?大家或许还记得基础篇讲解的守护线程与用户线程吧,JVM退出的条件是当前不存在用户线程,而线程池默认的ThreadFactory创建的线程是用户线程,

        static class DefaultThreadFactory implements ThreadFactory {
            ...
            public Thread newThread(Runnable r) {
                Thread t = new Thread(group, r,
                                      namePrefix + threadNumber.getAndIncrement(),
                                      0);
                if (t.isDaemon())
                    t.setDaemon(false);
                if (t.getPriority() != Thread.NORM_PRIORITY)
                    t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }
    

    如上代码可知线程池默认的线程工厂创建创建的都是用户线程。而线程池里面的核心线程是一直会存在的,如果没有任务则会阻塞,所以线程池里面的用户线程一直会存在.而shutdown方法的作用就是让这些核心线程终止,下面在简单看下shutdown重要代码:

        public void shutdown() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                ...
                //设置线程池状态为SHUTDOWN
                advanceRunState(SHUTDOWN);
                //中断所有的工作线程
                interruptIdleWorkers();
                ...
            } finally {
                mainLock.unlock();
            }
               ...
            }
    

    可知shutdown里面设置了线程池状态为SHUTDOWN,并且设置了所有工作线程的中断标志,那么下面在简单看下工作线程Worker里面是不是发现中断标志被设置了就会退出了。

      final void runWorker(Worker w) {
                ...
                try {
                while (task != null || (task = getTask()) != null) {
                   ...            
                }
                ...
              } finally {
                ...
            }
        }
    
    private Runnable getTask() {
            boolean timedOut = false; 
    
            for (;;) {
                ...
                //(1)
                if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                    decrementWorkerCount();
                    return null;
                }
                
                try {
                    //(2)
                    Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();
                    if (r != null)
                        return r;
                    timedOut = true;
                } catch (InterruptedException retry) {
                    timedOut = false;
                }
            }
        }
    

    如上代码正常情况下如果队列里面没有任务了,工作线程阻塞到代码(2)等待从工工作队列里面获取一个任务,这时候如果调用了线程池的shutdown命令而shutdown命令会中断所有工作线程,所以代码(2)会抛出处抛出InterruptedException异常而返回,而这个异常被catch了,所以继续执行代码(1),而shutdown时候设置了线程池的状态为SHUTDOWN所以getTask方法返回了null,所以runWorker方法退出循环,该工作线程就退出了。

    3、 总结

    本节通过一个简单的使用线程池异步执行任务案例介绍了线程池使用完后要如果不调用shutdown会导致线程池的线程资源一直不会被释放,然后通过源码分析了没有被释放的原因。所以日常开发中使用线程池的场景一定不要忘记了调用shutdown方法设置线程池状态和中断工作线程池

    以runWorker方法退出循环,该工作线程就退出了。

    4、 总结

    本节通过一个简单的使用线程池异步执行任务案例介绍了线程池使用完后要如果不调用shutdown会导致线程池的线程资源一直不会被释放,然后通过源码分析了没有被释放的原因。所以日常开发中使用线程池的场景一定不要忘记了调用shutdown方法设置线程池状态和中断工作线程池

    展开全文
  • 3.10 使用线程池时候当程序结束时候记得调用shutdown关闭线程池日常开发中为了便于线程的有效复用,线程池是经常会被用的工具,然而线程池使用完后如果不调用shutdown会导致线程池资源一直不会被释放。下面通过简单...

    3.10 使用线程池时候当程序结束时候记得调用shutdown关闭线程池

    日常开发中为了便于线程的有效复用,线程池是经常会被用的工具,然而线程池使用完后如果不调用shutdown会导致线程池资源一直不会被释放。下面通过简单例子来说明该问题。

    3.10.1问题复现

    下面通过一个例子说明当不调用线程池对象的shutdown方法后,当线程池里面的任务执行完毕后主线程这个JVM不会退出。

    public class TestShutDown {
    
            static void asynExecuteOne() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute one ---");
                }
            });
        }
        
        static void asynExecuteTwo() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute two ---");
                }
            });
        }
        
    
        public static void main(String[] args) {
           //(1)同步执行
            System.out.println("---sync execute---");
           //(2)异步执行操作one
            asynExecuteOne();
           //(3)异步执行操作two
            asynExecuteTwo();
           //(4)执行完毕
            System.out.println("---execute over---");
        }
    }
    

    如上代码主线程里面首先同步执行了操作(1)然后执行操作(2)(3),操作(2)(3)使用线程池的一个线程执行异步操作,我们期望当主线程和操操作(2)(3)执行完线程池里面的任务后整个JVM就会退出,但是执行结果却如下:

    image.png

    右上角红色方块说明JVM进程还没有退出,Mac上执行 ps -eaf|grep java 后发现Java进程还是存在的,这是什么情况那?修改操作(2)(3)在方法里面添加调用线程池的shutdown方法如下代码:

                static void asynExecuteOne() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute one ---");
                }
            });
            
            executor.shutdown();
        }
        
        static void asynExecuteTwo() {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new  Runnable() {
                public void run() {
                    System.out.println("--async execute two ---");
                }
            });
            
            executor.shutdown();
        }
    

    在执行就会发现JVM已经退出了,使用ps -eaf|grep java后发现Java进程以及不存在了,这说明只有调用了线程池的shutdown方法后当线程池任务执行完毕后线程池资源才会释放。

    3.10.2问题分析

    下面看下为何如此那?大家或许还记得基础篇讲解的守护线程与用户线程吧,JVM退出的条件是当前不存在用户线程,而线程池默认的ThreadFactory创建的线程是用户线程,

        static class DefaultThreadFactory implements ThreadFactory {
            ...
            public Thread newThread(Runnable r) {
                Thread t = new Thread(group, r,
                                      namePrefix + threadNumber.getAndIncrement(),
                                      0);
                if (t.isDaemon())
                    t.setDaemon(false);
                if (t.getPriority() != Thread.NORM_PRIORITY)
                    t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }
    

    如上代码可知线程池默认的线程工厂创建创建的都是用户线程。而线程池里面的核心线程是一直会存在的,如果没有任务则会阻塞,所以线程池里面的用户线程一直会存在.而shutdown方法的作用就是让这些核心线程终止,下面在简单看下shutdown重要代码:

        public void shutdown() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                ...
                //设置线程池状态为SHUTDOWN
                advanceRunState(SHUTDOWN);
                //中断所有的工作线程
                interruptIdleWorkers();
                ...
            } finally {
                mainLock.unlock();
            }
               ...
            }
    

    可知shutdown里面设置了线程池状态为SHUTDOWN,并且设置了所有工作线程的中断标志,那么下面在简单看下工作线程Worker里面是不是发现中断标志被设置了就会退出了。

      final void runWorker(Worker w) {
                ...
                try {
                while (task != null || (task = getTask()) != null) {
                   ...            
                }
                ...
              } finally {
                ...
            }
        }
    
    private Runnable getTask() {
            boolean timedOut = false; 
    
            for (;;) {
                ...
                //(1)
                if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                    decrementWorkerCount();
                    return null;
                }
                
                try {
                    //(2)
                    Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();
                    if (r != null)
                        return r;
                    timedOut = true;
                } catch (InterruptedException retry) {
                    timedOut = false;
                }
            }
        }
    

    如上代码正常情况下如果队列里面没有任务了,工作线程阻塞到代码(2)等待从工工作队列里面获取一个任务,这时候如果调用了线程池的shutdown命令而shutdown命令会中断所有工作线程,所以代码(2)会抛出处抛出InterruptedException异常而返回,而这个异常被catch了,所以继续执行代码(1),而shutdown时候设置了线程池的状态为SHUTDOWN所以getTask方法返回了null,所以runWorker方法退出循环,该工作线程就退出了。

    3.10.3 总结

    本节通过一个简单的使用线程池异步执行任务案例介绍了线程池使用完后要如果不调用shutdown会导致线程池的线程资源一直不会被释放,然后通过源码分析了没有被释放的原因。所以日常开发中使用线程池的场景一定不要忘记了调用shutdown方法设置线程池状态和中断工作线程池

    --------------------------------相约GitChat探讨技术--------------------------------------

    一、常用开源框架 Spring 扩展接口揭秘

    评价一个框架是否优秀,其中必有一点是看该框架是否留足了可扩展的接口。我们在实际做项目或者研发框架时,很多情况下就是在框架留出的扩展接口上进行定制,所以很有必要对这些框架留出了哪些扩展点,这些扩展点是干啥用的有个心知肚明的了解。

    本 Chat 将针对 Spring 扩展点进行介绍,主要内容包括:

    • 对 Spring 框架在容器刷新(Refresh 阶段),创建 Bean(getBean),容器销毁(destory)阶段中的扩展接口讲解

    • 对 Spring 中的 ContextLoaderListener 扩展接口进行讲解,并讲解 Webx 框架和 SpringMVC 框架如何使用它,从而让 Tomcat 与应用框架联系起来。

      最近微服务很火,

      二、SpringBoot核心模块原理剖析Chat(文章已经出炉)


      SpringBoot 以其轻量级,内嵌 Web 容器,一键启动,方便调试等特点被越来越多的微服务实践者所采用。然而知其然还要知其所以然,本节就来讲解 SpringBoot 的核心模块的实现原理,这些内容在面试的时候也是会被经常问到的:
    • spring-boot-load 模块,正常情况下一个类加载器只能找到加载路径的jar包里面当前目录或者文件类里面的*.class文件,SpringBoot 允许我们使用 java -jar archive.jar 运行包含嵌套依赖 jar 的 jar 或者 war 文件,那么 SpringBoot 是如何实现的那?

    • spring-boot-autoconfigure 模块,Auto-configuration 是 SpringBoot 在 Spring 的基础上提供的一个自动扫描 jar 包里面指定注解的类并注入到 Spring 容器的功能组件。

    • spring-boot 模块,提供了一些特性用来支持 SpringBoot 中其它模块。

      欢迎长按识别二维码加入本chat


    • 三、Java 类加载器揭秘Chat(文章已经出炉)

    类加载器作为 JVM 加载字节码到内存中的媒介,其重要性不言而喻,另外在职场面试时候也会被频繁的问道,了解类加载器的原理,能灵活的自定义类加载器去实现自己的功能显得尤为重要。

    主要内容:

    • 讲解 Java 中自带的三种类加载器,以及构造原理

    • 讲解类加载器原理

    • 讲解一种特殊的与线程相关类加载器

    • 讲解 Tomcat 框架中多级类加载器的实现原理

    • 讲解如何自定义类加载器实现模块隔离

      欢迎长按识别二维码加入本chat

    image
    展开全文
  • 没有引用指向且没有剩余线程的线程池将会自动关闭。 看一下线程池的构造方法 /** * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code ...
  • 大概说下问题(类似),就是新建一个线程池,核心线程是3个,最大线程数是6个,阻塞队列是12,过期时间是20s,假设每个线程处理完一个任务需要1s。如果一次性来了18 个任务,也就是线程全开,队列塞满,那么:3s之后...
  • 1. 线程池什么时候创建线程的? 2. 任务runnable task是先放到core到maxThread之间的线程,还是先放到队列? 3. 队列中的任务是什么时候取出来的? 4. 什么时候会触发reject策略? 5. core到maxThread之间的...
  • 线程池的优雅关闭 1.线程池的生命周期 2.正确关闭线程池的步骤 3.shutdown()与shutdownNow()的区别 shutdown() shutdownNow() 1ThreadPoolExecutor 核心数据结构 public class ThreadPoolExecutor ...
  • 线程池

    千次阅读 多人点赞 2017-07-17 11:22:43
    线程池什么线程池 线程池的组成部分 线程池的实现原理 线程池的应用场景 使用线程池的优缺点什么线程池线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务线程池...
  • Java 线程池会自动关闭吗?

    千次阅读 2019-12-07 19:49:44
    文章目录1. 线程池自动关闭的情况一:核心线程数为 0 并指定线程存活时间1.1. 手动创建线程池2.2 Executors.newCachedThrteadPool() 创建线程池2....首先我们需要了解线程池什么情况下会自动关闭。ThreadPoolExec...
  • 优雅关闭线程池

    2021-06-07 09:57:09
    文章目录前言why?how?相关参数shutdown跟shutdownNow区别具体关闭线程池代码参考资料 前言 这一类的文章在公众号其实是很多的,所以这一篇主要是加深自己对...新增一个关闭回调钩子,就是在jvm关闭时候会进行回调。
  • 平时开发中,大家更多的关注的是线程池的创建、任务的提交和执行。...大多知道需要调用shutdown()关闭线程池,也少研究其真正的关闭过程。 首先看源码中的一句注释: A pool that is no longer reference...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 78,812
精华内容 31,524
关键字:

线程池什么时候关闭