线程池和连接池学习总结

线程池     

1、流程

      先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。

2、作用
      线程池作用就是限制系统中执行线程的数量。
      根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

3、为什么要用线程池

     减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

     可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

4、 一个线程池的基本组成部分
      线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
      工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
      任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
      任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

5、常见线程池

①newSingleThreadExecutor

单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务

②newFixedThreadExecutor(n)

固定数量的线程池,没提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行

③newCacheThreadExecutor(推荐使用)

可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。

④newScheduleThreadExecutor

大小无限制的线程池,支持定时和周期性的执行线程

6、ThreadPoolExecutor详解

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

corePoolSize - 池中所保存的线程数,包括空闲线程。

maximumPoolSize-池中允许的最大线程数。

keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

unit - keepAliveTime 参数的时间单位。

workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。

threadFactory - 执行程序创建新线程时使用的工厂。

handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。

ThreadPoolExecutor是Executors类的底层实现。

7、拒绝策略

      AbortPolicy:这种策略直接抛出异常,丢弃任务。

      DiscardPolicy:丢弃任务,不抛出异常。

      DiscardOldestPolicy:阻塞

      CallerRunsPolicy:临时队列

8、相关面试题
    (1)Callable接口和Runable接口的区别

              1)Callable规定的方法是call(),而Runnable规定的方法是run()。

              2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

              3)call()方法可抛出异常,而run()方法是不能抛出异常的。

              4)运行Callable任务可拿到一个Future对象。

     (2) 什么是Future接口,干什么用的?

              Callable任务返回Future对象。即:Callable和Future一个产生结果,一个拿到结果。Future 表示异步计算的结果。Future接口提供方法来检测任务是否被执行完,等待任务执行完获得结果。也可以设置任务执行的超时时间,这个设置超时的方法就是实现Java程序执行超时的关键。

              所以,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现。

      (3)Callable可以在线程中使用吗(newThread(Runnable r))?

              单独使用Callable时,无法在新线程中(new Thread(Runnable r))使用,只能使用ExecutorService。

      (4)Callable怎么创建线程?

创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,该call()方法有返回值,再创建Callable实现类的实例。从java8开始,可以直接使用Lambda表达式创建Callable对象。
使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
调用FutureTask对象作为Thread对象的target创建并启动新线程。
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

       (5)线程调度策略有哪些?介绍一下?
                抢占式调度:抢占式调度指的是每条线程执行的时间、线程的切换都由系统控制,系统控制指的是在系统某种运行机制下,可能每条线程都分同样的执行时间片,也可能是某些线程执行的时间片较长,甚至某些线程得不到执行的时间片。在这种机制下,一个线程的堵塞不会导致整个进程堵塞。

                协同式调度:协同式调度指某一线程执行完后主动通知系统切换到另一线程上执行,这种模式就像接力赛一样,一个人跑完自己的路程就把接力棒交接给下一个人,下个人继续往下跑。线程的执行时间由线程本身控制,线程切换可以预知,不存在多线程同步问题,但它有一个致命弱点:如果一个线程编写有问题,运行到一半就一直堵塞,那么可能导致整个系统崩溃。

         (6)Executor, ExecutorService,Executors, ThreadPoolExecutor 分别解释一下

                 线程池的核心是ThreadPoolExecutor。Executor、Executors、ExecutorService、AbstractExecutorService这些接口或类都是ThreadPoolExecutor的祖宗。

                     Executor接口:是一个接口,这个接口只有一个方法void execute(Runnable command)方法。该方法提供一种将任务提交与每个任务将如何运行分离开来的方法。通常使用Executor的场景并不是显式地创建线程,而是只执行任务,实现线程的创建和线程的执行解耦。

                     ExecutorService:这个接口补充了十二个接口。因为它是接口,所以理所当然的并没有给出Executor接口中execute()方法的实现。Executors类为创建ExecutorService提供了便捷的工厂方法。接口ExecutorServie中有名如其义的几个方法:submit、shutdown、invokeAll、awaitTermination。

                    ThreadPoolExecutor:上面有解释

             (7)线程池怎么关闭,shutDown和shutDownNow有什么区别?

                      shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。而shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。

                      举个工人吃包子的例子,一个厂的工人(Workers)正在吃包子(可以理解为任务),假如接到shutdown的命令,那么这个厂的工人们则会把手头上的包子给吃完,没有拿到手里的笼子里面的包子则不能吃!而如果接到shutdownNow的命令以后呢,这些工人们立刻停止吃包子,会把手头上没吃完的包子放下,更别提笼子里的包子了。

================================================================================================================================================================================================

连接池

 1、连接池的作用:连接池是将已经创建好的连接保存在池中,当有请求来时,直接使用已经创建好的连接对数据库进行访问。这样省略了创建连接和销毁连接的过程。这样性能上得到了提高。

2、基本原理是这样的:

(1)建立数据库连接池对象(服务器启动)。
(2)按照事先指定的参数创建初始数量的数据库连接(即:空闲连接数)。
(3)对于一个数据库访问请求,直接从连接池中得到一个连接。如果数据库连接池对象中没有空闲的连接,且连接数没有达到最大(即:最大活跃连接数),创建一个新的数据库连接。
(4)存取数据库。
(5)关闭数据库,释放所有数据库连接(此时的关闭数据库连接,并非真正关闭,而是将其放入空闲队列中。如实际空闲连接数大于初始空闲连接数则释放连接)。
(6)释放数据库连接池对象(服务器停止、维护期间,释放数据库连接池对象,并释放所有连接)。

3、为什么要使用连接池?
    连接池放了N个Connection对象,本质上放在内存当中,在内存中划出一块缓存对象,应用程序每次从池里获得Connection对象,而不是直接从数据里获得,这样不占用服务器的内存资源。

4、如果不使用连接池会出现的情况:

       (1)占用服务器的内存资源
       (2)导致服务器的速度非常慢

5、连接池功能对比:

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值