首页 > 编程知识 正文

java线程池满了怎么办,java实现线程池

时间:2023-05-05 18:20:21 阅读:151028 作者:2586

java线程池配置ThreadPoolExecutor参与式publicthreadpoolexecutor (intcorepoolsize,int maximumPoolSize,long keepAliveTime, time unit unit blockingqueuerunnable work queue,ThreadFactory threadFactory, rejectedexecutionhandlerhandler (corepoolsize0||maximumpoolsize=0||maximumpoolsizecorepoolsize|) this.ACC=system.getsecuritymanager ()==null? null : access controller.get context (; this.corePoolSize=corePoolSize; this.maximumpoolsize=maximumpoolsize; this.workQueue=workQueue; this.keepalive time=unit.to nanos (keepalive time ); this.threadfactory=threadfactory; this.handler=handler; }参数说明corePoolSize——核心线程数。

例如,如果设置为5,则缺省情况下不会初始化线程。

如果程序提交任务总数少于6个,线程池将在接收到提交的线程时创建线程。

maximumPoolSize——最大线程数。 例如,如果设置为10,则在线程池中最多创建10个线程以供生存。

如果keepAliveTime,unit——线程数大于核心线程数,则为回收线程之前的空闲时间(以值和单位表示)。

例如,配置30秒,按上述5、10的例子,如果线程池中的线程大于5个,

如果立即可用的空闲时间超过30秒,线程将被回收。

工作队列——任务队列。 如果提交的任务需要排队处理,则任务将排队等待处理。

什么时候排队? 如果活动线程数大于或等于核心线程数,操作将排队。

什么时候创建大于核心线程数的线程?

当队列已满时,将调用线程创建方法,如果创建成功,当前任务将开始在新线程上执行。

线程数在线后怎么办? 执行拒绝策略。

threadFactory——线程工厂。

控制线程池中线程对象的创建,并在创建线程时设置线程名称,以控制线程是否在后台运行。

handler——拒绝了该策略。 如果任务既不能运行线程,也不能参与任务队列,则根据此策略进行处理

缺省情况下,它采用中断策略并抛出异常。

这意味着,如果需要提交并拒绝任务,则抛出RejectedExecutionException异常。

创建角色解释线程池后,提交任务时,如果线程池中的线程数小于核心线程,则每次提交任务时都会创建线程,直到拥有的线程数等于核心线程数

再次提交任务时,判断是否有空闲线程,如果有空闲线程,则直接执行任务,如果没有空闲线程,则执行排队操作(活动线程数等于核心线程数),将任务发送到http://www.sisi

ong>

        添加任务队列时,如果队列未满,则写入队列等待执行。如果队列已满,则执行新建线程流程。

        新建线程时,首先判断当前线程数是否达到最大线程数,没有达到则新建线程,并在线程中执行这次操作提交的任务,原来队列中的任务继续排队。如果线程数已达到最大线程数,则执行拒绝策略

        当线程数大于核心线程数时,执行线程回收流程,当线程空闲时间达到配置的保持活跃时间(keepAliveTime,unit)时,该空闲线程被回收。 

        创建线程的工作由线程工厂完成,创建线程时,设定线程名,是否后台线程,线程优先级。

线程池使用 // 单线程线程池,核心线程和最大线程均为1,任务队列大小为Integer.MAX_VALUE// 用于处理单线程排队任务ExecutorService executor = Executors.newSingleThreadExecutor();// 固定线程数线程池,核心线程和最大线程均为指定的线程数,任务队列大小为Integer.MAX_VALUE// 用于处理多线程并发处理,还可以指定线程工厂ExecutorService fixedExecutor = Executors.newFixedThreadPool(5);// 缓存线程池,核心线程数为0,最大线程数为Integer.MAX_VALUE,空闲时间为1分钟// 提交任务时,如果有空闲线程则使用空闲线程执行任务,如果没有则创建一个线程执行任务ExecutorService cachedExecutor = Executors.newCachedThreadPool();// 计划任务线程池,周期性执行,间隔一定时间触发执行ExecutorService scheduledExecutor = Executors.newScheduledThreadPool(5);

        虽然以上三个线程池可以满足大部分业务场景,但里面均没有合理的配置线程池必须的7个参数。实际使用时还要结合自己的场景来选择合适的线程池。

        首先需要考虑要解决的问题最多需要多少并发,实际场景有多少并发,自己的服务器又支持多少并发。一般情况下IO类型的可以多一些并发线程,毕竟IO过程消耗网卡资源,对CPU的消耗较小,CPU密集型任务一般不要超过CPU核数。

        然后需要选择合适的队列大小,尤其是对任务消耗时间未知,队列排队数量不可预估的情况下,必须制定合适的队列大小,并设置好拒绝策略。任务队列大小不限制的话默认为Integer.MAX_VALUE,这么多的Runnable对象,可能导致内存溢出。

        合适的拒绝策略,在任务数超过我们预期的情况时会发挥作用,默认的拒绝策略会抛出异常,指示出线程池有问题了。

线程池的作用

        最后简单说一下我理解的线程池的作用。

        1. 线程池解决了创建线程消耗资源的问题,主要是通过复用线程整体上减少了资源开销。详情见最后的测试结果(线程与任务耗时测试)。

        2. 解决了线程管理的问题,线程作为系统资源,是宝贵而又有限的,程序使用线程又有较高的技术要求,否则可能导致线程资源耗尽,内存溢出,CPU使用率高等问题。

        3. 降低了线程使用的门槛,简化了多线程使用方法,通过使用线程池,可以帮助我们更高效的编写简单,优雅,高效的程序。             

测试内容

线程与任务耗时测试-个人电脑测试结果:

线程池使用newCachedThreadPool,结果如下:

1万次任务提交,测试10次1万次线程启动测试10次41ms~48ms304ms~357ms

测试代码如下:

// 1万次任务 private static void testTask(){ long t1 = System.nanoTime(); ExecutorService cachedExecutor = Executors.newCachedThreadPool(); for(int i=0;i<10000;i++){ cachedExecutor.submit(new Runnable() { @Override public void run() { } }); } cachedExecutor.shutdown(); long t2 = System.nanoTime(); System.out.println("RunTask:"+(t2-t1)); } //1万次线程 private static void testThread(){ long t1 = System.nanoTime(); for(int i=0;i<10000;i++){ new Thread().start(); } long t2 = System.nanoTime(); System.out.println("RunThread:"+(t2-t1)); }

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。