动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

线程池的参数详解

05-24 16:31 741浏览
举报 T字号
  • 大字
  • 中字
  • 小字

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这其中涉及到了很多的参数问题,下面我们就统一地讲一下线程池的参数问题。

1. 任务队列(workQueue)

任务队列是基于阻塞队列实现的,即采用生产者消费者模式,在Java中需要实现BlockingQueue接口。但Java已经为我们提供了7种阻塞队列的实现:

  • ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列(数组结构可配合指针实现一个环形队列)。
  • LinkedBlockingQueue: 一个由链表结构组成的有界阻塞队列,在未指明容量时,容量默认为Integer.MAX_VALUE。
  • PriorityBlockingQueue: 一个支持优先级排序的无界阻塞队列,对元素没有要求,可以实现Comparable接口也可以提供Comparator来对队列中的元素进行比较。跟时间没有任何关系,仅仅是按照优先级取任务。
  • DelayQueue:类似于PriorityBlockingQueue,是二叉堆实现的无界优先级阻塞队列。要求元素都实现Delayed接口,通过执行时延从队列中提取任务,时间没到任务取不出来。
  • SynchronousQueue: 一个不存储元素的阻塞队列,消费者线程调用take()方法的时候就会发生阻塞,直到有一个生产者线程生产了一个元素,消费者线程就可以拿到这个元素并返回;生产者线程调用put()方法的时候也会发生阻塞,直到有一个消费者线程消费了一个元素,生产者才会返回。
  • LinkedBlockingDeque: 使用双向队列实现的有界双端阻塞队列。双端意味着可以像普通队列一样FIFO(先进先出),也可以像栈一样FILO(先进后出)。
  • LinkedTransferQueue: 它是ConcurrentLinkedQueue、LinkedBlockingQueue和SynchronousQueue的结合体,但是把它用在ThreadPoolExecutor中,和LinkedBlockingQueue行为一致,但是是无界的阻塞队列。

注意有界队列和无界队列的区别:如果使用有界队列,当队列饱和时并超过最大线程数时就会执行拒绝策略;而如果使用无界队列,因为任务队列永远都可以添加任务,所以设置maximumPoolSize没有任何意义。

2.线程工厂(threadFactory)

线程工厂指定创建线程的方式,需要实现ThreadFactory接口,并实现**newThread(Runnable r)**方法。该参数可以不用指定,Executors框架已经为我们实现了一个默认的线程工厂:

/** * The default thread factory. 
*/private static class DefaultThreadFactory implements ThreadFactory 
{    
private static final AtomicInteger poolNumber = new AtomicInteger(1);    
private final ThreadGroup group;    
private final AtomicInteger threadNumber = new AtomicInteger(1);    
private final String namePrefix;     
DefaultThreadFactory() 
{        
SecurityManager s = System.getSecurityManager();        
group = (s != null) ? 
s.getThreadGroup() :                              Thread.currentThread().getThreadGroup();        
namePrefix = "pool-" +                      
poolNumber.getAndIncrement() +  "-thread-";    
}     
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;    }
}

3.拒绝策略(handler)

当线程池的线程数达到最大线程数时,需要执行拒绝策略。拒绝策略需要实现RejectedExecutionHandler接口,并实现**rejectedExecution(Runnable r, ThreadPoolExecutor executor)**方法。不过Executors框架已经为我们实现了4种拒绝策略:

  • AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。
  • CallerRunsPolicy:由调用线程处理该任务。
  • DiscardPolicy:丢弃任务,但是不抛出异常。可以配合这种模式进行自定义的处理方式。
  • DiscardOldestPolicy:丢弃队列最早的未处理任务,然后重新尝试执行任务。

线程池中需要我们记忆的参数数据其实不多,我们只要重点掌握上述的几个参数就足够了,至于想深入学习线程池中的各种类型的参数的小伙伴可以通过查阅资料或者观看动力节点在线的视频课程获取更多的信息。

0人推荐
共同学习,写下你的评论
0条评论
代码小兵652
程序员代码小兵652

113篇文章贡献392215字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

提枪策马乘胜追击04-21 20:01

Spring常见面试题

代码小兵92504-17 16:07

Java零基础实战项目——五子棋

代码小兵98804-25 13:57

Java string类详解

杨晶珍05-11 14:54

6道经典算法面试题

杨晶珍05-12 16:39

发评论

举报

0/150

取消