对Java语言线程池进行深入了解
小标 2018-10-12 来源 : 阅读 970 评论 0

摘要:本文主要向大家介绍了对Java语言线程池进行深入了解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了对Java语言线程池进行深入了解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。


多线程开发越来越常见,开发者常常使用多线程完成一些耗时操作,通过并发来提高系统的响应速度。尤其是在Android移动端开发,为了提升用户体验,常常将一些操作放在异步线程中完成。但是,如果一味滥用多线程,会造成系统资源浪费,而且常常会出现并发问题。因此线程的管理就是一个非常重要的事,线程池也就应运而生。


线程池使用意义:


1)降低系统资源的消耗,线程池中实现线程的复用技术减少无限量的线程创建,减少线程创建和销毁带来的资源浪费;


2)提高响应速度,当有异步任务需要执行时,若线程中有空闲线程存在那么可以快速响应,无需新创建线程;


3)提高线程的可管理性,线程本身是一种稀缺资源,无节制的创建线程除了会造成资源浪费,而且会降低系统稳定性,带来许多并发问题。线程池对线程进行统一的管理、分配。


线程池的好处已经显而易见,若是系统中频繁创建线程来执行任务可以采用线程池技术;反之,若频率相对较低也不需要强行使用线程池。总体而言,根据系统的设计来定方案。


线程池的使用:


1、创建线程池,解析其构造函数:


/**

  * Creates a new {@code ThreadPoolExecutor} with the given initial

  * parameters.

  *

  * @param corePoolSize the number of threads to keep in the pool, even

  *  if they are idle, unless {@code allowCoreThreadTimeOut} is set

  * @param maximumPoolSize the maximum number of threads to allow in the

  *  pool

  * @param keepAliveTime when the number of threads is greater than

  *  the core, this is the maximum time that excess idle threads

  *  will wait for new tasks before terminating.

  * @param unit the time unit for the {@code keepAliveTime} argument

  * @param workQueue the queue to use for holding tasks before they are

  *  executed.  This queue will hold only the {@code Runnable}

  *  tasks submitted by the {@code execute} method.

  * @param threadFactory the factory to use when the executor

  *  creates a new thread

  * @param handler the handler to use when execution is blocked

  *  because the thread bounds and queue capacities are reached

  * @throws IllegalArgumentException if one of the following holds:

 

  *{@code corePoolSize < 0}

 

  *{@code keepAliveTime < 0}

 

  *{@code maximumPoolSize <= 0}

 

  *{@code maximumPoolSize < corePoolSize}

  * @throws NullPointerException if {@code workQueue}

  *or {@code threadFactory} or {@code handler} is null

  */

 public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler) {

  if (corePoolSize < 0 ||

maximumPoolSize <= 0 ||

maximumPoolSize < corePoolSize ||

keepAliveTime < 0)

throw new IllegalArgumentException();

  if (workQueue == null || threadFactory == null || handler == null)

throw new NullPointerException();

  this.corePoolSize = corePoolSize;

  this.maximumPoolSize = maximumPoolSize;

  this.workQueue = workQueue;

  this.keepAliveTime = unit.toNanos(keepAliveTime);

  this.threadFactory = threadFactory;

  this.handler = handler;

 }</runnable>

   


1)corePoolSize(核心线程数):可以理解为线程池的基本线程数量,正常情况下,如果线程池的线程数量小于核心线程数,当有任务提交到线程池执行时,会直接创建一个线程执行。当线程数量大于等于corePoolSize时便不再直接创建线程。


2)maximumPoolSize(最大线程数):线程池可以容纳的最大线程数量,当线程池中的线程数量大于等于maximumPoolSize时便交给饱和策略,不可以再创建新的线程。


3)keepAliveTime(线程保留时间):线程池的工作线程执行完任务后,可以保留空闲状态的时间,用于控制空闲线程的保存时间。当线程数量小于等于corePoolSize时,该时间设置之后无用。


4)unit(保留时间单位):线程存活时间的单位。天、小时、分、秒等。


5)workQueue(任务队列):用于保存等待执行任务的阻塞队列。可以选择以下集中队列:


ArrayBlockingQueue:基于数组实现的有界阻塞队列,遵循FIFO原则;


LinkedBlockingQueue:基于链表实现的有界阻塞队列,遵循FIFO原则。吞吐量高于ArrayBlockingQueue。Executors.newFixedThreadPool()使用该队列。


public static ExecutorService newFixedThreadPool(int nThreads) {

  return new ThreadPoolExecutor(nThreads, nThreads,

  0L, TimeUnit.MILLISECONDS,

  new LinkedBlockingQueue<runnable>());

 }</runnable>

   


SynchronousQueue:不存储元素的阻塞队列,每当任务想要插入时,就会进入阻塞状态,只有等到另外一个线程调用移除操作才会被唤醒。吞吐量高于LinkedBlockingQueue,Executors.newCachedThreadPool()使用该队列。


public static ExecutorService newCachedThreadPool() {

 return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

 60L, TimeUnit.SECONDS,

 new SynchronousQueue<runnable>());

}</runnable>

   


PriorityBlockingQueue:具有优先级的无限阻塞队列。


6)threadFactory(线程工厂):用于创建线程工厂类,通常情况下可以不指定,因为有另外一个构造方法指定类默认的线程工厂,Executors.defaultThreadFactory()。


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;

  }

 }

   


7)handler(饱和处理策略):当线程池的工作队列已满,而且线程数大于等于maximumPoolSize时,若再提交新的任务,则会将其交给饱和策略处理。java中提供了几种处理策略,默认策略为AbortPolicy。


AbortPolicy:直接抛出异常。


CallerRunsPolicy:只用调用者所在线程来运行任务。


DiscardOldestPolicy:丢弃队列中最近的一个任务,并执行当前任务。


DiscardPolicy:不处理,不丢弃。


2、向线程池提交任务:


execute()方法:


  threadPoolExecutor.execute(new Runnable() {

@Override

public void run() {

 System.out.println("run task by execute");

}

  });

   


submit()方法:


  Future<!--?--> future = threadPoolExecutor.submit(new Runnable() {

@Override

public void run() {

 System.out.println("run task by submit");

}

  });

   


上述2个方法均可以向线程池提交任务,其最大区别在于是否需要返回值。execute方法没有返回值,submit方法会返回一个Future对象,该对象可以获取任务执行的结果。


3、线程池关闭:


线程池关闭是通过遍历线程中所有的工作线程,然后逐个调用线程的interrupt方法中断线程,因此并不能保证所有线程都能停止,不响应中断的任务则无法终止。


1)shutdown():将线程池的状态设置成SHUTDOWN状态,然后中断所有没有执行任务的线程(中断空闲线程)


2)shutdownNow():将线程池的状态设置成STOP状态,尝试停止所有正在执行或者暂停任务的线程(所有线程),并返回等待执行任务的列表。


线程池原理分析:


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 1
看完这篇文章有何感觉?已经有2人表态,50%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程