初步认识线程池

1.什么是线程池

    线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务执行由线程池来管理。为了充分利用CPU多核提升性能 采用多线程并发计算

2.线程池作用主要有两个

   不同请求之间重复利用线程 无需频繁创建和销毁线程 降低系统开销和控制线程数量上限避免创建过多耗尽内存空间减少线程上下文切换次数

3.线程池创建与使用

   JDK1.5中增加了内置线程池实现ThreadPoolExecutor

   newSingle(单)ThreadExecutor:一个单线程的线程池。如果因异常结束,会再创建一个新的,保证按照提交顺序执行。

   newFixed(固定)ThreadPool:创建固定大小的线程池。根据提交的任务逐个增加线程,直到最大值保持不变。如果因异常结束,会新创建一个线程补充

   newCachedT(缓存)hreadPool:创建一个可缓存的线程池。会根据任务自动新增或回收线程。

   newScheduled(周期性)ThreadPool:支持定时以及周期性执行任务的需求。

   newWorkStealingPool:JDK8新增,根据所需的并行层次来动态创建和关闭线程,通过使用多个队列减少竞争,底层使用ForkJoinPool(分支合并池)来实现。优势在于可以充分利用多CPU,把一个任务拆分成多个“小任务”,放到多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。

4.Executors部分方法的弊端:

   newFixedThreadPool和newSingleThreadExecutor主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。

 newCachedThreadPool和newScheduledThreadPool:主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

5.阿里巴巴java开发规范中推荐了3种线程池创建方式。

    方式一,引入commons-lang3包。

    方式二,引入com.google.guava包。

    方式三,spring配置线程池方式:自定义线程工厂bean需要实现ThreadFactory,可参考该接口的其它默认实现类,使用方式直接注入bean,调用execute(Runnable task)方法即可。

除以上方法,还可以通过ThreadPoolExecutor的构造方法直接创建线程池,上述方法最终也是创建了ThreadPoolExecutor对象 然后堆积进行包装。

6.什么情况下使用线程池拒绝策略:

   当任务不断过来,而系统此时又处理不过来时,我们就需要采用对应策略拒绝服务。

   Abort(中止)Policy策略:该策略会直接抛出异常,阻止系统正常工作

   CallerRuns(调用者运行)Policy策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

   DiscardOlddest(丢弃旧的)Policy策略:该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务

   Discard(丢弃)Policy策略:该策略默默的丢弃无法处理的任务不予任何处理

除了这四种 还可以根据业务需求自定义拒绝策略。

7.线程池的执行

   创建完线程池以后当向线程池提交任务是通常使用execute(执行)方法。

线程池运行图如下


8.execute与submit方法的区别

   execute适用于不需要关注返回值的场景。

   submit适用于需要关注返回值的场景。

9.异常处理

   当执行任务是发生异常,正常可以通过try...catch捕获异常并进行处理的。

   如果很多线程默认异常处理机制相同,可以通过Thread类的UncaughtExceptionHandler(未捕获异常处理程序)来设置县城默认的异常处理机制。

   实现UncaughtExceptionHandler接口调用:

   Thread#setUncaughtExceptionHandler方法。

   如果想设置为全局默认异常处理机制则可以用:

   Thread#setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)方法。

   注意:使用UncaughtExceptionHandler处理异常的方法只适用于execute方法执行任务,对sumit方法无效。Sumit执行的任务可以通过返回的future对象的get方法接受抛出的异常再进行处理 这也是两个方法的差别之一。

10.线程池中常见的队列

    ArrayBlockingQueue(有界队列):是一个用数组实现的有界阻塞队列,按FLFO排序。

   LinkedBlockingQueue(链接 阻塞队列):可设置容量队列,基于链表结构的阻塞队列,按照FLFO排序任务,容量自行设置不设置的话,就是一个无边界的阻塞队列,最大长度为lnteger.MAX_VALUE。

   DelayQueue(延迟队列):一个任务定时周期的延迟执行的队列,根据执行时间从小到大排列,否则根据插入先后排列。newScheduledThreadPool使用了这个队列。

   priorityBlockingQueue(优先级队列):具有优先级的无界阻塞队列。

   SynchronouQueue(同步队列):不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,newCachedThreadPool线程池使用了这个队列。

10.关闭线程池

   可以调用shutdown(关闭)Now和shutdown两个方法实现。

   shutdownNow:对正在执行的认为有全部发出interrupt(),停止执行,对还未开始的任务全部撤销,并且返回还未开始的任务列表

   shutdown:调用后线程池不再接受新的任务,但也不会强制终止已经提交或者正在执行的任务。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值