Java中的线程池有什么用
发表于:2024-11-19 作者:千家信息网编辑
千家信息网最后更新 2024年11月19日,这篇文章主要讲解了"Java中的线程池有什么用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Java中的线程池有什么用"吧!Java中的线程池【1】使
千家信息网最后更新 2024年11月19日Java中的线程池有什么用
这篇文章主要讲解了"Java中的线程池有什么用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Java中的线程池有什么用"吧!
Java中的线程池
【1】使用线程池的好处:
1)降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗。2)提高响应速度,当任务到达时,任务可以不需要等到线程创建就能立即执行。3)提高线程的可管理性。线程池可以进行统一分配、调优和监控线程。
【2】构造方法:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);参数说明: 1)corePoolSize:核心池的大小。 1)在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务。 2)默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务。 注意:即使其它空闲的线程能够执行新任务也会去创建线程,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。 3)调用prestartAllCoreThreads()或prestartCoreThread()方法来预创建线程,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。 2)workQueue:任务缓存队列,是一个阻塞队列,用来存储等待执行的任务;类型为BlockingQueue ,通常可以取下面4种类型: 1)ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小; 2)LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE,吞吐量通常要高于ArrayBlockingQueue。 eg:静态工厂方法Executors.newFixedThreadPool()就是使用的这个队列。 3)SynchronousQueue:这个队列不会保存提交的任务,而是直接新建一个线程来执行新来的任务。 说明:每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue。 eg:静态工厂方法Executors.newCachedThreadPool使用的就是这个队列。 4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。 说明: 1>一般使用LinkedBlockingQueue和SynchronousQueue 2>建议使用有界队列,有界队列能增加系统的稳定性。 eg:如果线程池里的工作线程全部阻塞,任务积压在线程池里,如果设置成无界队列,那么这个队列会越来越大,有可能会撑满内存,导致整个系统不可用。 3)maximumPoolSize:线程池中允许创建的最大线程数。 1)如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程来执行任务。 2)如果使用了无界的任务队列,则这个参数就不起什么作用了(队列默认的大小是:Integer.MAX_VALUE,在队列未满之前,线程池是不会再去创建新线程了)。 4)RejectedExecutionHandler:任务拒绝策略,当任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略: 1)ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常,默认使用该策略。 2)ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常;会导致被丢弃的任务无法再次被执行 3)ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程);会导致被丢弃的任务无法再次被执行 4)ThreadPoolExecutor.CallerRunsPolicy: 由调用线程处理该任务;主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 说明:也可以实现RejectedExecutionHandler接口来自定义策略。 5)keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。 默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用。 但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0; 6)TimeUnit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性: TimeUnit.DAYS; 天 TimeUnit.HOURS; 小时 TimeUnit.MINUTES; 分钟 TimeUnit.SECONDS; 秒 TimeUnit.MILLISECONDS; 毫秒 TimeUnit.MICROSECONDS; 微妙 TimeUnit.NANOSECONDS; 纳秒 7)ThreadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。
【3】其它方法:
任务的提交: execute(Runnable command): 提交后没有返回值,故无法判断任务是否被线程池执行成功。 submit(): 提交后返回一个Future对象,通过这个future对象可以判断任务是否执行成功。 通过future的get()方法来获取返回值,该方法会阻塞当前线程直到任务完成。 get(long timeout, TimeUnit unit)方法:阻塞当前线程一段时间后立即返回,这时候任务可能没有执行完。线程池容量的动态调整: setCorePoolSize() 设置核心池的大小 setMaximumPoolSize() 设置线程池最大能创建的线程数线程池的关闭: 原理:遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。 shutdown() 1>将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。 2>不再接受新的任务,但是不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止。 shutdownNow() 1>首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并且清空任务缓存队列,并返回等待执行任务的列表. 说明: 1)只要调用了这两个关闭方法中的任意一个,isShutdown方法就会返回true。 2)当所有的任务都已关闭后,才表示线程池关闭成功,这时调用isTerminaed方法会返回true。
【4】线程池的状态:
// RUNNING状态:线程池正常运行,可以接受新的任务并处理队列中的任务private static final int RUNNING = -1 << COUNT_BITS;// SHUTDOWN状态:不再接受新任务,但是会执行队列中的任务private static final int SHUTDOWN = 0 << COUNT_BITS;// STOP状态:不再接受新任务,不处理队列中的任务,中断正在处理的任务private static final int STOP = 1 << COUNT_BITS;// 过渡状态:所有的任务都执行完了,线程池已经没有有效的线程了,此时线程池的状态为过渡状态,并且将要调用terminated()方法private static final int TIDYING = 2 << COUNT_BITS;// 终止状态:terminated()方法调用完成后的状态private static final int TERMINATED = 3 << COUNT_BITS;1>当线程池刚创建后,线程池处于RUNNING状态,可以接受新的任务并处理队列中的任务2>如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;3>如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;4>当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。
【5】线程池的处理流程:
ThreadPoolExecutor执行execute方法分下面4种情况。 1)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。 2)如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。 3)如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。 4)如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用 RejectedExecutionHandler.rejectedExecution()方法。
感谢各位的阅读,以上就是"Java中的线程池有什么用"的内容了,经过本文的学习后,相信大家对Java中的线程池有什么用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
线程
任务
队列
方法
状态
处理
缓存
阻塞
大小
情况
策略
参数
工厂
正在
尝试
运行
最大
成功
作用
就是
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
学生成绩数据库er图
管家婆数据库密码忘记
构筑网络安全平台
sql和数据库合并
手抄报关于网络安全简单的
kettel数据库使用教程
网络安全手抄报 易画8k纸
数据库自增 安全
软件开发缺陷怎么提
网络安全审查和实名制
视频存放数据库app
公有云服务器安全
如何打开数据库脚本文件
数据库最新技术
湖南网络安全咨询就业前景好
因为改数据库正在使用
贵阳分布式存储服务器
网络安全客户端怎么设置
可诺心思网络技术
做网络安全学什么
数据库中学号字段的类型是什么
网络安全技术分析 论文)
sql数据库怎么生成数据字典
网络安全法条例的是
因为改数据库正在使用
笔记本做私人服务器
如何写接口将文件写入数据库
逆时代全球网络技术
互联网科技服务公司开业致辞
十大网络安全证书