java线程池

在本人参与的项目里面,实际上能写多线程代码的地方并不多,只有线程池接触的稍微多一点,下面主要写本人对于线程池的理解,在讲具体线程池之前,有一些基础概念需要铺垫:

设计模式方面

1、工厂模式
工厂模式属于创建型模式。主要是定义一个接口,让其子类自己决定实例化哪个工厂类。
优点:松耦合,调用者无需关注对象是如何创建的,只需要传递接口、方法和参数即可。
一个常见的例子如下:需要一辆汽车,可以直接从工厂里面提货,而不用管汽车是怎么做出来的。
2、享元模式
使用共享物件,用来尽可能减少内存使用量等。java的String常量池以及数据库连接池也用到了享元模式。
3、生产者-消费者模式
生产者-消费者模式并不属于23种设计模式。理解起来就是一句话:生产者负责生产,消费者负责消费,各司其职。
以上设计模式这里不详细讲,后续会专门开一篇博客讲设计模式。

阻塞队列

阻塞队列的特点如下:
1) 当阻塞队列为空时,从队列中获取元素的操作将被阻塞
2) 担当阻塞队列满时,往队列中添加元素的操作被阻塞
有边界阻塞队列:ArrayBlockingQueue,SynchronousQueue,LinkedBlockingQueue(长度Integer.MAX_VALUE)
无边界阻塞队列: PriorityBlockingQueue,DelayQueue,LinkedTransferQueue,LinkedBlockingDeque(双向阻塞队列)

线程池参数

线程池定义的参数一共7个,如下:

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

其中有4个是比较重要的:
1)corePoolSize:核心线程数,核心线程会一直存活。当线程数小于核心线程数时,即使现有线程空闲,也会有限创建新的线程来执行任务。
2)maximumPoolSize:最大线程数,表明在池里面的最大线程数量。
3)keepAliveTime:当线程空闲时间达到keepAliveTime时,该线程会退出,直到线程数量等于corePoolSize。
4)workQueue:在队列里面的任务。这里定义为:BlockingQueue。
线程池执行顺序如下:
1) 当线程数小于核心线程数时,创建新线程
2) 当线程数大于等于核心线程数且队列未满时,将任务放入队列
3) 当线程数大于核心线程数且队列已满,此时线程数小于maximumPoolSize,则新建
4) 当核心线程数,队列,最大线程数都满,则抛异常

四种的线程池

1、newCachedThreadPool:newCachedThreadPool的定义如下:

return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());

从定义中可以得知,该线程池的核心线程数为0,最大线程数为2147483647(反编译后的值,实际上应该是Integer.MAX_VALUE),队列使用的SynchronousQueue:不存储元素的阻塞队列。也就是说,不会限制其线程数量,新进任务将直接开启线程,所以缺点很明显了:线程数量无法控制,很可能由于大量线程导致系统延迟甚至大量线程消耗资源引起OOM。

2、newFixedThreadPool:newFixedThreadPool的定义如下:

return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

从定义中可以得知,该线程池的核心线程数为和最大线程数值是一样的,队列使用的LinkedBlockingQueue,而LinkedBlockingQueue虽然是有边界阻塞队列,但是其边界为:Integer.MAX_VALUE,可以等同于无边界队列了。所以缺点很明显了:虽然核心线程数固定,不会由于无限的线程导致OOM,但是由于队列里面可以放置大量的任务,很可能由于无限任务放置进去导致空间不够,进而造成OOM。

3、newScheduledThreadPool:newScheduledThreadPool的定义如下:

return new ScheduledThreadPoolExecutor(corePoolSize);
super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue());

指定核心线程,最大线程数为Integer.MAX_VALUE,队列使用的DelayedWorkQueue():一种设计为定时任务的延迟队列,是无边界队列。newScheduledThreadPool支持定时及周期性任务执行。缺点和newCachedThreadPool一样
4、newSingleThreadExecutor:newSingleThreadExecutor的定义如下:

return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));

该线程池,核心线程和最大线程是一样的,队列为LinkedBlockingQueue,缺点和newFixedThreadPool一样,有一点需要注意,由于核心线程是指定的,固其工作线程数将一直都是1个,也就是这是一个单线程化的线程池

如何设置线程池参数:

阿里开发规范手册里面明确强制:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,原因上面有讲,四种线程池的缺点。
那么自己创建线程池,如何设置参数呢:首先,BlockingQueue以及keepAliveTime需要根据自己具体的业务来看。另外,核心线程数以及最大线程数的选择,可参考博客:
线程池参数设置.

发布了8 篇原创文章 · 获赞 2 · 访问量 185

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览